friend type屬性 一個 多個 引用 定義 ret 安全 cto

工廠模式

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 o;
}

var person1 = createPerson("tom",20,"trtr");
var person2 = createPerson("tom1",24,"httt");

優點:使用同一個接口創建很多獨享,避免大量的重復代碼。
缺點:沒有解決對象識別問題,怎樣知道一個對象的類型。

構造函數模式

構造函數就是為了解決工廠模式的缺點,將它的實例標識為一種特定類型。
缺點:每個方法都要在每個實例撒很重新創建一遍。

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

var person1 = new Person("gr",12,"Grgr");
var person2 = new Person("gr44",45,"4y4");

原型模式

每個函數都有一個prototype的原型屬性,是一個指針,指向一個對象,這個對象的用途是包含可以由特定類型的所有實例共享的屬性和方法。

優點:讓所有對象實例共享它所包含的屬性和方法。將這些信息直接添加到原型對象中。

function Person(){

}
Person.prototype.name = "tom";
Person.prototype.age = 29;
Person.prototype.jobn = "ghrrh";
var person = new Person();

原型模式下的一個坑

function Person(){

}
Person.prototype.name = "tom";
Person.prototype.age = 29;
Person.prototype.job = "ghrrh";

//有些時候為了圖方面會將其寫成下面這樣
Person.prototype = {
    name: "tom",
    age: 29,
    job: "ghrrh"
}
//但是這時候無意間就重寫了默認的prototype對象,因此constructor屬性變成了新對象的constructor屬性(指向Object構造函數),不再指向Person函數
var person = new Person();

對了這裏還要介紹一個原型對象:

無論什麽時候,創建一個新函數,就會根據一組特定的規則創建一個prototype屬性,這個屬性會指向prototype對象。在默認情況下,所有原型對象都會獲得一個constructor屬性,這個屬性包含一個指向prototype屬性所在函數的指針。
技術分享圖片

缺點:

實際上,很少的人會單獨使用原型模式,因為原型模式是讓所有對象實例都共享一個原型對象上的屬性和方法。
對於基本類型還可以,可以在實例中定義,然後覆蓋原型中的,但是對於引用類型,修改一個實例上(person1)的一個引用類型的屬性,就會引起另一個實例(person2)的引用類型的改變,其實我們要的不是這種效果。因此出現構造函數和原型模式結合使用。

組合使用構造函數模式和原型模式

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

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

var person1 = new Person("tom",20,"hhtt");
var person2 = new Person("tom1",45,"chengxuyuan");

動態原型模式

有時候像這種分開寫構造和原型,很可能會感到非常困惑。
動態原型模式解決這個問題,它將所有信息都封裝在了構造函數中,而通過在構造函數中初始化原型(僅在必要的情況下)。

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);
        }
    }
}

寄生構造函數模式

建議在可以使用其他模式的情況下,不要使用這種模式。

穩妥構造函數模式

穩妥對象:顧名思義,就是很穩妥,指的是沒有公共屬性,而且其方法也不引用this的對象。穩妥對象最適合在一些安全的環境中(這些環境中會禁止使用this和new)。

function Person(naem,age,job){
    var o = new Object();

    o.sayName = function(){
        alert(name);
    }
}

var friend = new Person("gg",20,"ghrhr");
friend.sayName(); //gg

總結:最開始是工廠模式。
為了標識特定類型的對象,出現構造函數模式。
為了減少創建多個沒有多大關系的實例,浪費內存,出現原型模式。
為了減少修改一個實例上的屬性而影響到另一個實例的屬性,此時出現原型模式和構造函數相結合的模式。
至於後來的動態原型模式,寄生構造函數模式,穩妥構造函數模式,這些自己斟酌使用。
總結在這裏,為大家提供一種記憶思路。

JavaScript之幾種創建函數的區別以及優缺點。