js-JavaScript常见的建立对象的几种方式

一、经过Object构造函数或对象字面量建立单个对象

  这些方式有明显的缺点:使用同一个接口建立不少对象,会产生大量的重复代码。为了解决这个问题,出现了工厂模式。函数

二、工厂模式

  考虑在ES中没法建立类(ES6前),开发人员发明了一种函数,用函数来封装以特定接口建立对象的细节。(实现起来是在一个函数内建立好对象,而后把对象返回)。this

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

var person1=createPerson("Nicholas",29,"Software Engineer");
var person2=createPerson("Greg",27,"Doctor");

  函数createPerson()可以根据接受的参数来构建一个包含全部必要信息的Person对象。工厂模式虽然解决了建立多个类似对象的问题,但却没有解决对象识别的问题,即怎么知道一个对象的类型。随着JS发展,又一个模式出现了。spa

三、构造函数模式

  像Object和Array这样的原生构造函数,在运行时会自动出如今执行环境。此外,也能够建立自定义的构造函数,从而定义自定义对象类型的属性和方法。prototype

function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.sayName=function(){
        alert(this.name);
    };
}

var person1=new Person(...);
var person2=new Person(...);

  与工厂模式相比,具备如下特色:指针

  1. 没有显式建立对象;
  2. 直接将属性和方法赋给了this对象;
  3. 没有return语句;
  4. 要建立新实例,必须使用new操做符;(不然属性和方法将会被添加到window对象)
  5. 可使用instanceof操做符检测对象类型

  构造函数的问题:code

  构造函数内部的方法会被重复建立,不一样实例内的同名函数是不相等的。可经过将方法移到构造函数外部解决这一问题,但面临新问题:封装性很差。对象

  这些问题可经过原型模式解决。blog

四、原型模式

  咱们建立的每一个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含能够由特定类型的全部实例共享的属性和方法。(prototype就是经过调用构造函数而建立的那个对象实例的原型对象)。接口

  使用原型对象的好处是可让全部对象实例共享它所包含的属性和方法。换句话说,没必要在构造函数中定义对象实例的信息,而是能够将这些信息直接添加到原型对象中。内存

function Person(){
}

Person.prototype.name="Nicholas";
Person.prototype.age=29;
Person.prototype.job="...";
Person.prototype.sayName=function(){
    ...
};

var person1=new Person();
person1.sayName();//"Nicholas"

  更常见的作法是用一个包含全部属性和方法的对象字面量来重写整个原型对象,并重设constructor属性

function Person(){
}

Person.prototype={
    name:"...",
    age:29,
    job:"...",
    sayName:function(){
        ...
    }
};

Object.defineProperty(Person.prototype,"constructor",{
    enumerable:false,
    value:Person,
});

  原型对象的问题:

  1. 他省略了为构造函数传递初始化参数这一环节,结果全部实例在默认状况下都将取得相同的属性值,虽然这会在必定程度带来必定的不便,但不是最大的问题,最大的问题是由其共享的本性所决定的。
  2. 对于包含基本值的属性能够经过在实例上添加一个同名属性隐藏原型中的属性。而后,对于包含引用数据类型的值来讲,会致使问题。

  这些问题致使不多单独使用原型模式。

五、组合使用构造函数模式和原型模式

  这是建立自定义类型的最多见的方式

  构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。因此每一个实例都会有本身的一份实例属性的副本,但同时共享着对方法的引用,最大限度的节省了内存。同时支持向构造函数传递参数。

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

Person.prototype={
    constructor:Person,
    sayName:function(){
        alert(this.name);
    }
};

var person1=new Person(...);

六、动态原型模式

function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;

    if(typeof this.sayName!="function"){
        Person.prototype.sayName=function(){
            alert(this.name);
        };
    }
}

  这里只有sayName()不存在的状况下,才会将它添加到原型中,这段代码只会在初次调用构造函数时才执行。这里对原型所作的修改,可以马上在全部实例中获得反映。

七、Object.create()

  ES5定义了一个名为Object.create()的方法,它建立一个新对象,其中第一个参数是这个对象的原型,第二个参数对对象的属性进行进一步描述。

八、另有寄生构造函数模式和稳妥构造函数模式

相关文章
相关标签/搜索