美文网首页
JavaScript中创建对象的几种方式

JavaScript中创建对象的几种方式

作者: 蘑菇均 | 来源:发表于2019-03-27 23:35 被阅读0次

    在《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
    

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

    相关文章

      网友评论

          本文标题:JavaScript中创建对象的几种方式

          本文链接:https://www.haomeiwen.com/subject/nzwxbqtx.html