欢迎光临
我们一直在努力

JavaScript | 面向对象编程之创建对象

文章目录

字面量模式

一般的,都会使用对象字面量形式创建对象。

var person = {
    name:'sanrenyan',
    age :22,
    job :'none',
    speak:function(){
        alert(this.name+'____________'+this.age)
    }
};
person.speak();

字面量对象创建单个对象时比较方便,但创建多个对象时,可能会产生大量重复的代码。

工厂模式

工厂模式抽象了创建具体对象的过程,用函数来封装创建对象的细节。

//工厂模式
function creatPerson(name,age){
    var person = new Object;
    person.name = this.name;
    person.age = this.age;
    person.speak = function(){
        alert(this.name+"————"+this.age);
    }
};

var per1 = creatPerson("zhang",18);
var per2 = creatPerson("zhao",20);

工厂模式的缺点在于:它无法判断实例化出来的对象的具体的类型是什么。这时候我们就引出了自定义构造函数来解决这个问题。

构造函数模式

通过自定义的构造函数,进行定义自定义对象类型的属性和方法。创建自定义的构造函数可以将他的实例表示为一种特定类型。构造函数模式没有显示的创建对象,直接把属性和方法赋给this对象,没有return语句。

function creatPerson(name,age){
    this.name = name;
    this.age = age;
    this.speak = function(){
        alert(this.name+"————"+this.age);
    }
}

var per1 = new creatPerson("liu",10);
var per2 = new creatPerson("li",17);
per1.speak();

基本构造函数的缺点在于,每次创建对象都会创建对象下的函数,而这些函数一般工作又是相同的,如此一来,很浪费内存。

构造函数拓展

在构造函数的基础上,把方法定义在构造函数外部,可以有效地解决内存。

function creatPerson(name,age){
    this.name = name;
    this.age = age;
    this.speak = speak;
}
speak = function(){
    alert(this.name+"————"+this.age);
}
var per1 = new creatPerson("liu",10);
var per2 = new creatPerson("li",17);
per1.speak();
alert(per1.speak === per2.speak);

寄生构造函数模式

寄生构造函数模式是工厂模式和构造函数模式的结合,创建的函数的作用仅仅是封装创建对象的代码,然后返回新创建的对象。

寄生构造函数模式与构造函数模式有相同的问题,每个方法都要在每个实例向重新创建一遍,因此同样会浪费内存。

除此之外,使用寄生构造函数模式返回的对象与构造函数之间没有关系,使用instanceof或prototype属性都没有意义,因此这个模式几乎很少用。

//寄生构造函数
function person(age,name){
    var person = new Object;
    person.age = age;
    person.name = name;
    person.speak = function(){
        alert(this.name +"——"+this.age);
    }
    return person;
}
var person1 = new person("zhang",18);
var person2 = new person("zhao",11);
//具有相同作用的sayName()方法在person1和person2这两个实例中却占用了不同的内存空间
console.log(person1.sayName === person2.sayName);//false
console.log(person1 instanceof Person);//false
console.log(person1.__proto__ === Person.prototype);//false

稳妥构造函数模式

所谓稳妥对象指没有公共属性,而且其方法也不引用this的对象。稳妥对象最适合在一些安全环境中(这些环境会禁止使用this和new)或者在防止数据被其他应用程序改动时使用。

稳妥构造函数与寄生构造函数模式相似,但有两点不同:一是新创建对象的实例方法不引用this;二是不使用new操作符调用构造函数。

与寄生构造函数模式相似,使用稳妥构造函数模式创建的对象与构造函数之间也没有什么关系,因此instanceof操作符对这种对象也没有什么意义。

function Person(name,age,job){
    //创建要返回的对象
    var o = new Object();
    //可以在这里定义私有变量和函数
    //添加方法
    o.sayName = function(){
        console.log(name);
    };
    //返回对象
    return o;
}
//在稳妥模式创建的对象中,除了使用sayName()方法之外,没有其他方法访问name的值
var friend = Person("bai",29,"Software Engineer");
friend.sayName();//"bai"

原型模式

原型模式的有点在于,可以让所有实例共享他的属性和方法。也就是说,不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中。

//原型对象模式
function gteObj(){
    gteObj.prototype.hobby = ["唱","跳","RAP"];
}
var obj1 = new gteObj();
var obj2 = new gteObj();
console.log(obj1.hobby,obj2.hobby);// ["唱", "跳", "RAP"] (3) ["唱", "跳", "RAP"]
console.log(obj1.hobby === obj2.hobby); //true

为了减少不必要的输入,也为了从视觉上更好地封装原型的功能,用一个包含所有属性和方法的对象字面量来重写整个原型对象。

但是,经过对象字面量的改写后,constructor不再指向Person了。因为此方法完全重写了默认的prototype对象,使得Person.prototype的自有属性constructor属性不存在,只有从原型链中找到Object.prototype中的constructor属性。

function Person(){};
Person.prototype = {
    name: "bai",
    age: 29,
    job: "software Engineer",
    sayName : function(){
        console.log(this.name);
    }
};
var person1 = new Person();
person1.sayName();//"bai"
console.log(person1.constructor === Person);//false
console.log(person1.constructor === Object);//true

原型模式问题在于引用类型值属性会被所有的实例对象共享并修改,这也是很少有人单独使用原型模式的原因。

组合模式(重点)

组合使用构造函数模式和原型模式是创建自定义类型的最常见方式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性,这种组合模式还支持向构造函数传递参数。实例对象都有自己的一份实例属性的副本,同时又共享对方法的引用,最大限度地节省了内存。该模式是目前使用最广泛、认同度最高的一种创建自定义对象的模式。

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["shelby","Court"];
}
Person.prototype = {
    constructor: Person,
    sayName : function(){
        console.log(this.name);
    }    
}
var person1 = new Person("bai",29,"Software Engineer");
var person2 = new Person("hu",25,"Software Engineer");
person1.friends.push("Van");
alert(person1.friends);// ["shelby","Court","Van"];
alert(person2.friends);// ["shelby","Court"];
alert(person1.friends === person2.friends);//false
alert(person1.sayName === person2.sayName);//true
赞(0) 打赏
未经允许不得转载:散人研 » JavaScript | 面向对象编程之创建对象
分享到: 更多 (0)

评论 抢沙发

6 + 9 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏