JS紅寶書之建立物件的多種方式
借鑑了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 的物件。