1. 程式人生 > 其它 >JS紅寶書之建立物件的多種方式

JS紅寶書之建立物件的多種方式

技術標籤:JS深入系列javascript前端工廠方法模式

借鑑了github裡冴羽大佬的筆記,讓我在讀紅寶書的時候通暢很多。地址:https://github.com/mqyqingfeng/Blog

雖然Object建構函式或物件字面量可以用來建立單個物件,但使用同一個介面建立很多物件,會產生大量的重複程式碼。

6.2.1 工廠模式

function createPerson (name,age){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.getName = function() {
        console.
log(this.name) } return o; } var person1 = createPerson("Pinocchio",14)

他雖然解決了建立很多相似物件的問題,但卻沒有解決物件識別問題,因為所有例項都指向一個原型。

6.2.2 建構函式模式

function Person(name,age){
    this.name = name;
    this.age = age;
    this.getName = function(){console.log(this.name);}
}
var person1 = new Person
("Pinocchio",14)

**優點:**每個例項可以識別為一個特定的型別。 缺點:每次建立例項時,每個方法都要被建立一次。

這種方式會經歷以下四個步驟:

  • 刻在堆記憶體中建立一個新的物件
  • 將建構函式的作用域賦給新物件(因此this指向這個新物件)
  • 執行建構函式中的程式碼(為這個新物件新增屬性)
  • 將新建的物件作為返回值

alert(person1 instanceof Object); //true 所有物件都是Object例項,同時person1也是Person的例項

6.2.3 建構函式模式的優化

function Person(name,age){
    this.name =
name; this.age = age; this.getName = getName } function getName(){ console.log(this.name) } var person1 = new Person("Pinocchio",14)

**優點:**解決了每個方法都要被重新建立的問題。 **缺點:**這就沒有封裝的效果了。別的人也可以用getName函式。

6.2.4 原型模式

每個函式都有一個prototype(原型)屬性,這個屬性是一個指標,指向一個物件。

function Person(){
    Person.prototype.name = "Pinocchio";
    Person.prototype.age = 14;
    Person.prototype.getName = function(){console.log(this.name);}
}
var person1 = new Person();
var person2 = new Person();
alert(person1.getName == person2.getName);   //true

**優點:**方法不會被重新建立 。 **缺點:**所有屬性和方法都共享,無法初始化引數。比如原型中有一個引用型別,那麼一個例項屬性的改變會導致另一個例項屬性也發生改變。

6.2.5 組合模式:使用建構函式+原型模式

建構函式模式用於定義例項屬性,原型模式用於定義方法和共享的屬性。

function Person(name,age){
    this.name = name;
    this.age = age;
    this.friends = ['li','wang'];
}
Person.prototype = {
    constructor:Person;
    sayName(){
        alert(this.name)
    }
}
var person1 = new Person('dsa',23)

**優點:**該共享的共享,該私有的私有,使用最廣泛的方式。

**缺點:**沒有寫在一起,即更好的封裝性

6.2.6 動態原型模式

function Person(name,age){
	this.name = name;
    this.age = age;
    if(typeof this.sayName != "function"){
        Person.prototype.sayName = function(){
            alert(this.name)
        }
    }
}
var person1 = new Person('dsa',14)

**優點:**將組合模式更好的封裝起來。

上面用if判斷,是防止每次new Person()時都呼叫一次Person.prototype.sayName=function(){}。

加個if判斷,就只有在第一次new Person()時,構建一次sayName函式。第二次再new Person()時,由於原型鏈上已經有sayName函數了,typeof this.sayName等於’function’,就不用再構建sayName函數了。

6.2.7 寄生建構函式模式

寄生在建構函式的一種方法。

function SpecialArray(){
    var values = new Array();
    values.push(...arguments);
    values.toPipedString = function(){
        return this.join('|')
    }
}
var colors = new SpecialArray('red','blue','green')

這樣方法可以在特殊情況下使用。比如我們想建立一個具有額外方法的特殊陣列但是又不想直接修改Array建構函式,我們可以這樣寫。

但是這種 new 出來的物件與建構函式或者與建構函式的原型屬性之間沒有關係。

6.2.8 穩妥建構函式模式

function person(name){
    var o = new Object();
    o.sayName = function(){
        console.log(name);
    };
    return o;
}
var person1 = person('kevin');
person1.sayName(); // kevin
person1.name = "daisy";
person1.sayName(); // kevin
console.log(person1.name); // daisy

所謂穩妥物件,指的是沒有公共屬性,而且其方法也不引用 this 的物件。