原型鏈
在JavaScript原型(一)中晶姊,我們介紹了每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象扒接,原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針,而實(shí)例都包含一個(gè)指向原型對(duì)象的內(nèi)部指針。
ECMAScript 中描述了原型鏈的概念,并將原型鏈作為實(shí)現(xiàn)繼承的主要方法涛救。其基本思想是利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法夹供。
基本概念
如果原型對(duì)象等于另一個(gè)類型的實(shí)例,此時(shí)的原型對(duì)象將包含一個(gè)指向另一個(gè)原型的指針,相應(yīng)地,另一個(gè)原型中也包含著一個(gè)指向另一個(gè)構(gòu)造函數(shù)的指針。假如另一個(gè)原型又是另一個(gè)類型的實(shí)例凝垛,那么上述關(guān)系依然成立,如此層層遞進(jìn)蜓谋,就構(gòu)成了實(shí)例與原型的鏈條梦皮,即原型鏈。
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
};
function SubType(){
this.subproperty = false;
}
//繼承了SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue()); //true
以上述代碼為例桃焕,其原型鏈如下圖所示剑肯。可以看出SuperType的prototype指向其原型對(duì)象观堂,SubType的原型是一個(gè)SuperType實(shí)例让网,而每個(gè)SuperType都會(huì)指向其構(gòu)造函數(shù)的原型對(duì)象,這樣就形成了原型鏈师痕。
在JavaScript中溃睹,每個(gè)對(duì)象都繼承自O(shè)bject,因此胰坟,上述原型鏈的完整結(jié)構(gòu)如下圖所示
可以通過instanceof 操作符確定原型和實(shí)例之間的關(guān)系因篇。只要用這個(gè)操作符來測試實(shí)例與原型鏈中出現(xiàn)過的構(gòu)造函數(shù),結(jié)果就會(huì)返回true笔横。
alert(instance instanceof Object); //true
alert(instance instanceof SuperType); //true
alert(instance instanceof SubType); //true
原型式繼承
ECMAScript 5 通過新增Object.create()方法規(guī)范化了原型式繼承竞滓。這個(gè)方法接收兩個(gè)參數(shù):
- 一個(gè)用作新對(duì)象的原型對(duì)象(可選的)
- 另一個(gè)為新對(duì)象定義額外屬性的對(duì)象
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
var anotherPerson2 = Object.create(person, {
name: {
value: "Greg"
}
});
alert(anotherPerson2.name); //"Greg"
原型式繼承,可以在不必預(yù)先定義構(gòu)造函數(shù)的情況下實(shí)現(xiàn)繼承吹缔,其本質(zhì)是執(zhí)行對(duì)給定對(duì)象的淺復(fù)制虽界。而復(fù)制得到的副本還可以得到進(jìn)一步改造。需要注意的是涛菠,包含引用類型值的屬性始終都會(huì)共享相應(yīng)的值,就像使用原型模式一樣。
還有一點(diǎn)需要注意俗冻,即在通過原型鏈實(shí)現(xiàn)繼承時(shí)礁叔,不能使用對(duì)象字面量創(chuàng)建原型方法。因?yàn)檫@樣做就會(huì)重寫原型鏈迄薄。原型鏈雖然很強(qiáng)大琅关,可以用它來實(shí)現(xiàn)繼承,但它也存在一些問題讥蔽。其中涣易,最主要的問題來自包含引用類型值的原型。
參考:《JavaScript高級(jí)程序設(shè)計(jì)第三版》