創(chuàng)建對(duì)象
我們都知道面向?qū)ο蠖加蓄惖母拍钔奘蓿?ES5 里面卻沒有類的概念菇民,因此它的對(duì)象也與基于類的語(yǔ)言中的對(duì)象有所不同。
在一開始的時(shí)候投储,我們可以通過原生 Object 或者對(duì)象字面量的方式來創(chuàng)建對(duì)象第练,例如
var person1 = {
name: "steven",
age: 21
};
var person2 = {...};
var person3 = {...};
可是當(dāng)我們使用同一個(gè)接口創(chuàng)建對(duì)象,就會(huì)產(chǎn)生大量的重復(fù)代碼玛荞。為了解決這個(gè)問題娇掏,人們開始使用工廠模式的一種變體。
工廠模式
function createPerson(name, age) {
var o = new Object();
o.name = name;
o.age = age;
return o
}
var person1 = createPerson("Steven", 21);
var person2 = createPerson(...);
這個(gè)方式解決了重復(fù)代碼的問題勋眯,卻沒有解決對(duì)象識(shí)別的類型(即怎樣知道一個(gè)對(duì)象的類型)婴梧。隨著 JavaScript 的發(fā)展,出現(xiàn)了構(gòu)造函數(shù)模式客蹋。
構(gòu)造函數(shù)模式
function Person(name, age){
this.name = name;
this.age = age;
this.sayName = function() {
alert(this.name);
};
}
var person1 = new Person("Steven", 21);
var person2 = new Person(...);
比起工廠模式塞蹭,構(gòu)造函數(shù)模式具有以下特點(diǎn):
- 沒有顯示創(chuàng)建對(duì)象
- 直接將屬性和方法賦給 this 對(duì)象
- 沒有 return 語(yǔ)句
其中調(diào)用構(gòu)造函數(shù)會(huì)經(jīng)歷以下步驟:
- 創(chuàng)建一個(gè)新對(duì)象
- 將構(gòu)造函數(shù)的作用域賦給了新對(duì)象(因此 this 就指向了這個(gè)對(duì)象)
- 執(zhí)行構(gòu)造函數(shù)中的代碼
- 返回新對(duì)象
除此之外,創(chuàng)建自定義的構(gòu)造函數(shù)意味著將來可以將它的實(shí)例標(biāo)示為一種特定的類型讶坯,而正是構(gòu)造函數(shù)模式勝過工廠模式的地方番电。
alert(person1.constructor == Person); // True
alert(person2.constructor == Person); // True
注意:按照慣例,構(gòu)造函數(shù)始終應(yīng)該以一個(gè)大寫字母開頭辆琅,而非構(gòu)造函數(shù)則應(yīng)該以一個(gè)小寫字母開頭钧舌。
然而我們注意到,每個(gè)方法都要在每個(gè)實(shí)例重新創(chuàng)建一遍涎跨,然而這些方法其實(shí)都是公有的洼冻。因此,我們可以采用原型模式隅很。
原型模式
我們知道撞牢,我們創(chuàng)建的每一個(gè)函數(shù)都有一個(gè) prototype (原型)屬性率碾。使用原型對(duì)象的好處是,所有對(duì)象實(shí)例可以共享它所包含的屬性和方法屋彪。
function Person(){}
Person.prototype.name = "Steven";
Person.prototype.age = 21;
Person.prototype.sayName = function() {
alert(this.name);
};
var person1 = new Person();
var person2 = new Person();
然而如果把屬性放在原型鏈上會(huì)導(dǎo)致兩個(gè)問題:
- 無法初始化參數(shù)所宰,導(dǎo)致所有實(shí)例取得相同的屬性值
- 原型中所有的屬性會(huì)被實(shí)例共享
為了解決上面問題,可以把構(gòu)造函數(shù)和原型模式結(jié)合起來畜挥,這樣即可以利用構(gòu)造函數(shù)初始化參數(shù)并保存不同屬性仔粥,也可以引用同樣的方法。
組合使用
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.constructor = Person;
Person.prototype.sayName = function() {
alert(this.name);
};
var person1 = new Person("Steven", 21);
var person2 = new Person(...);
目前在 ES5 中蟹但,這種構(gòu)造函數(shù)與原型混成的模式躯泰,是使用最廣泛和認(rèn)同度最高的創(chuàng)建自定義類型的方法。