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()的方法,它建立一個新對象,其中第一個參數是這個對象的原型,第二個參數對對象的屬性進行進一步描述。

八、另有寄生構造函數模式和穩妥構造函數模式

相關文章
相關標籤/搜索