JavaScript中创建对象的几种方式

 在《JavaScript高级程序设计》中,介绍了创建对象的7种方式,分别是:工厂模式、构造函数模式、原型模式、构造函数和原型组合模式、动态原型模式、寄生构造函数模式以及稳妥构造函数模式。

下面分别具体介绍下这几种模式。

一、工厂模式

通过函数来封装以特定接口创建对象的细节。

案例:

function createPerson(name,age,job){
    var o = new Object();
        o.name = name;
        o.age = age;
        o.job = job;
        o.sayName = function(){
            console.log(this.name);
        }
    return o;
}

var p1 = new createPerson("xiaoLe",23,"Engineer");
var p2 = new createPerson("xiaoDing",31,"Doctor");

这种方式的好处在于可以快速创建相似的对象,问题在于无法区分对象类型[如p1和p2都是Object类型]。于是出现了构造函数模式。

 

二、构造函数模式

 案例:

function Person(name,age,job){  
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
        console.log(this.name);
    }
}
var p1 = new Person("xiaoLe",23,"Engineer");
var p2 = new Person("xiaoDing",31,"Doctor");

//构造函数模式产生的问题
console.log(p1.sayName() == p2.sayName());//false

    构造函数模式与工厂模式的区别是,没有显式地创建对象、属性和方法直接赋给this对象、没有return语句;在使用构造函数创建对象时,必须使用new操作符。

    通过构造函数模式创建的实例,可以通过instanceof操作符来判断其类型。但不足是,若构造函数中有方法,那么每个方法都会在实例上重新创建一遍,而这是没有必要的。但如果将构造函数中的方法挪到构造函数外,那这个方法又变成全局函数。为了解决这个问题,从而出现了原型模式。

 

三、原型模式

案例:

function Person(){
}

Person.prototype = {
    constructor:Person,
    name:"xiaoMi",
    age : 30,
    job : "Engineer",
    sayName = function(){
        console.log(this.name);
    }
};

var p1 = new Person();
p1.sayName();//"xiaoMi"
var p2 = new Person();
p2.sayName();//"xiaoMi"
console.log(p1.sayName() == p2.sayName());//true

//原型模式的问题
Person.prototype.friends = ["huawei","vivo"]
var p3 = new Person();
var p4 = new Person();

p3.friends.push("oppo");
console.log(p3.friends);//"huawei","vivo","oppo"
console.log(p3.friends === p4.friends);//true   

    原型模式实现了属性和方法被实例共享,实例可以通过重新属性实现属性值个性化,但是这只有在属性类型为基本类型时才有效,如果属性类型为引用类型,就会出现上面friends属性的问题。为了解决这个问题,出现了构造函数和原型组合模式。

 

四、构造函数和原型组合模式

案例:

function Person(name,age,job){   
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["huawei","vivo"];
}

Person.prototype = {
    constructor:Person,
    sayName:function(){
        console.log(this.name);
    }
}
var p1 = new Person("xiaoMi",23,"Engineer");
var p2 = new Person("xiaoLe",23,"Engineer");

p1.friends.push("oppo");
console.log(p1.friends);//"huawei","vivo","oppo"
console.log(p2.friends);//"huawei","vivo"

        这种模式顾名思义就是组合使用构造函数模式和原型模式,其中,构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性。这也是目前创建自定义类型的最常见方式.

五、动态原型模式

案例:

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    if( typeof this.sayName != "function"){
        Person.prototype.sayName = function(){
                console.log(this.name);
        }
    }
}

var p1 = new Person("xiaoLe",23,"Engineer");

    使用构造函数和原型组合模式时,往往是将构造函数和原型分开写,容易让人产生困惑,于是出现了这种模式,将所有信息都封装在构造函数中,通过在构造函数中初始化原型。

六、寄生构造函数模式

案例:

function SpecialArray(){
    var values = new Array();
    values.push.apply(values,arguments);
    //添加方法---特别处
    values.toPipedString = function(){
        return this.join("|");
    }
    return values;
 }
var colors = new SpecialArray("red","blue","green");
console.log(colors.toPipedString());//"red|blue|green"

这种模式可以在特殊情况下[比如对一些引用类型增加额外方法,同时又不想修改该引用类型的原型]用来为对象创建构造函数。

七、稳妥构造函数模式

案例:

function Person(name,age,job){
    var o = new Object();
    o.sayName = function(){
        console.log(name);
    }
    return o;
}

var p1 = Person("xiaoLe",23,"Engineer");
p1.sayName();//xiaoLe

    该模式适合在某些安全执行环境。

 

你可能感兴趣的:(前端填坑)