Javascript實(shí)現(xiàn)繼承的幾種方式

1内边、構(gòu)造函數(shù)模式

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

function Person(name,age,job){

this.name = name;

this.age = age;

this.job = job;

this.sayName = function(){

alert(this.name);

};

}

varperson1 = new Person("Nicholas",29,"Software Engineer");

varperson2 = new Person("Greg",27,"Doctor");

person1.sayName();//"Nicholas"

person2.sayName();//"Greg"

alert(person1.constructor == Person);//true

alert(person2.constructor == Person);//true

alert(person1 instanceof Object);//true

alert(person1 instanceof Person);//true

alert(person2 instanceof Object);//true

alert(person2 instanceof Person);//true

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

問題:

每個(gè)方法都要在每個(gè)實(shí)例上重新創(chuàng)建一遍堰酿。在前面的例子中埂息,person1和person2都有一個(gè)名為sayName()的方法区丑,但那兩個(gè)方法不是同一個(gè)Function的實(shí)例师妙。

alert(person1.sayName ==person2.sayName);//false

然而呢撞,創(chuàng)建兩個(gè)完成同樣任務(wù)的Function實(shí)例的確沒有必要狮鸭;況且有this對(duì)象在,根本不用在執(zhí)行代碼前就把函數(shù)綁定到特定對(duì)象上面牌柄。因此畸悬,可以通過把函數(shù)定義轉(zhuǎn)移到構(gòu)造函數(shù)外部來解決這個(gè)問題:

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

function Person(name,age,job){

this.name = name;

this.age = age;

this.job = job;

this.sayName = sayName;

}

functionsayName(){

alert(this.name);

}

varperson1 = new Person("Nicholas",29,"Software Engineer");

varperson2 = new Person("Greg",27,"Doctor");

alert(person1.sayName == person2.sayName);//true

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

問題:在全局作用域中定義的函數(shù)實(shí)際上只能被某個(gè)對(duì)象調(diào)用,這讓全局作用域有點(diǎn)名不副實(shí)珊佣。更讓人無法接受的是:如果對(duì)象需要定義很多方法蹋宦,那么就要定義很多個(gè)全局函數(shù),于是我們這個(gè)自定義的引用類型就絲毫沒有封裝性可言了咒锻。

2冷冗、原型模式

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

function Person(){

}

Person.prototype.name = "Nicholas";

Person.prototype.age = 29;

Person.prototype.job = "Software Engineer";

Person.prototype.sayName = function(){

alert(this.name);

};

varperson1 = new Person();

person1.sayName();//"Nicholas"

varperson2 = new Person();

person2.sayName();//"Nicholas"

alert(person1.sayName == person2.sayName);//true

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

理解原型:無論什么時(shí)候,只要?jiǎng)?chuàng)建了一個(gè)新函數(shù)惑艇,就會(huì)根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個(gè)prototype屬性蒿辙。在默認(rèn)情況下,所有prototype屬性都會(huì)自動(dòng)獲得一個(gè)constructor(構(gòu)造函數(shù))屬性滨巴,這個(gè)屬性包含一個(gè)指向prototype屬性所在函數(shù)的指針思灌。Person.prototype.constructor指向Person。創(chuàng)建了自定義的構(gòu)造函數(shù)之后恭取,其原型屬性默認(rèn)只會(huì)取得constructor屬性泰偿;至于其他方法,則都是從object繼承而來的蜈垮。當(dāng)調(diào)用構(gòu)造函數(shù)創(chuàng)建一個(gè)新實(shí)例后耗跛,該實(shí)例的內(nèi)部將包含一個(gè)指針(內(nèi)部屬性),指向構(gòu)造函數(shù)的原型屬性攒发。在很多實(shí)現(xiàn)中调塌,這個(gè)內(nèi)部屬性的名字是_proto_。不過惠猿,要明確的真正重要一點(diǎn)羔砾,就是這個(gè)鏈接存在于實(shí)例與構(gòu)造函數(shù)的原型屬性之間,而不是存在于實(shí)例與構(gòu)造函數(shù)之間。

file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg

alert(Person.prototype.isPrototypeOf(person1));//true

alert(Person.prototype.isPrototypeOf(person2));//true

每當(dāng)代碼讀取某個(gè)對(duì)象的某個(gè)屬性時(shí)蜒茄,都會(huì)執(zhí)行一次搜索唉擂,目標(biāo)是具有給定名字的屬性。搜索首先從對(duì)象實(shí)例本身開始檀葛。如果在實(shí)例中找到了具有給定名字的屬性玩祟,則返回該屬性的值;如果沒有找到屿聋,則繼續(xù)搜索指針指向的原型對(duì)象空扎,在原型對(duì)象中查找具有給定名字的屬性。如果在原型對(duì)象中找到了這個(gè)屬性润讥,則返回該屬性的值转锈。雖然可以通過對(duì)象實(shí)例訪問保存在原型中的值,但卻不能通過對(duì)象實(shí)例重寫原型中的值楚殿。如果在實(shí)例中添加一個(gè)與原型中屬性同名的屬性撮慨,則該屬性會(huì)屏蔽原型中的那個(gè)屬性。添加的同名屬性只會(huì)阻止我們?cè)L問原型中的那個(gè)屬性脆粥,但不會(huì)修改那個(gè)屬性砌溺。即使將這個(gè)屬性設(shè)置為null,也只會(huì)在實(shí)例中設(shè)置這個(gè)屬性变隔,而不會(huì)恢復(fù)其指向原型的鏈接规伐。不過,使用delete操作符則可以完全刪除實(shí)例屬性匣缘,從而讓我們嫩鞏固重新訪問原型中的屬性猖闪。in操作符只要通過對(duì)象能訪問到屬性就返回true。hasOwnProperty()只在屬性存在于實(shí)例中時(shí)才返回true肌厨。

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

function Person(){

}

Person.prototype.name = "Nicholas";

Person.prototype.age = 29;

Person.prototype.job = "Software Engineer";

Person.prototype.sayName = function(){

alert(this.name);

};

varperson1 = new Person();

varperson2 = new Person();

alert(person1.hasOwnProperty("name"));//false

alert("name" in person1);//true

person1.name = "Greg";

alert(person1.name);//"Greg"

alert(person1.hasOwnProperty("name"));//true

alert("name" in person1);//true

deleteperson1.name;

alert(person1.name);//"Nicholas"

alert(person1.hasOwnProperty("name"));//false

alert("name" in person1);//true

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

更簡單的原型語法:

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

Person.prototype = {

name : "Nicholas",

age : 29,

job: "Software Engineer",

sayName : function(){

alert(this.name);

}

};

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

在上面代碼中培慌,我們將Person.prototype設(shè)置為等于一個(gè)以對(duì)象字面量形式創(chuàng)建的新對(duì)象。本質(zhì)上完全重寫了默認(rèn)的prototype對(duì)象夏哭,因此constructor屬性也就變成了新對(duì)象的屬性指向Object構(gòu)造函數(shù)检柬,不再指向Person函數(shù)献联。盡管instanceof操作符還能返回正確的結(jié)果竖配,但是constructor已經(jīng)無法確定對(duì)象的類型了。如果constructor的值真的很重要里逆,可以特意設(shè)置回適當(dāng)?shù)闹担?/p>

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

Person.prototype = {

constructor : Person,

name : "Nicholas",

age : 29,

job: "Software Engineer",

sayName : function(){

alert(this.name);

}

};

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

由于在原型中查找值的過程是一次搜索进胯,因此我們對(duì)原型對(duì)象所作的任何修改都能夠立即從實(shí)例上反映出來,即使是先創(chuàng)建了實(shí)例后修改原型也照樣如此原押。比如新定義一個(gè)person.sayHi();胁镐,其原因可以歸結(jié)為實(shí)例與原型之間松散連接的關(guān)系。但如果是重寫整個(gè)原型對(duì)象,那情況就不一樣盯漂。我們知道颇玷,調(diào)用構(gòu)造函數(shù)時(shí)會(huì)為實(shí)例添加一個(gè)指向最初原型的_proto_指針,而把原型修改為另外一個(gè)對(duì)象就等于切斷了構(gòu)造函數(shù)與最初原型之間的聯(lián)系就缆。

原型對(duì)象的問題:首先帖渠,它省略了為構(gòu)造函數(shù)傳遞初始化參數(shù)這一環(huán)節(jié),結(jié)果所有實(shí)例在默認(rèn)情況下都將取得相同的屬性值竭宰。這還不是最大的問題空郊,最大的問題是由其共享的本性所導(dǎo)致的。對(duì)于包含引用類型值得屬性來說切揭,就會(huì)出現(xiàn)嚴(yán)重問題狞甚。

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

function Person(){

}

Person.prototype = {

constructor : Person,

name : "Nicholas",

age : 29,

job : "Software Engineer",

friends :["Shelby","Court"],

sayName : function(){

alert(this.name);

}

};

varperson1 = new Person();

varperson2 = new Person();

person1.friends.push("Van");

alert(person1.friends);//"Shelby,Court,Van"

alert(person2.friends);//"Shelby,Court,Van"

alert(person1.friends === person2.friends);//true

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

3、組合使用構(gòu)造函數(shù)模式和原型模式

構(gòu)造函數(shù)模式用于定義實(shí)例屬性廓旬,而原型模式用于定義方法和共享的屬性哼审。結(jié)果,每個(gè)實(shí)例都會(huì)有自己的一份實(shí)例屬性和副本孕豹,但同時(shí)又共享這對(duì)方法的引用棺蛛,最大限度地節(jié)省了內(nèi)存。另外巩步,這種混成模式還支持向構(gòu)造函數(shù)傳遞參數(shù)旁赊,可謂是集兩種模式之長。這種模式是目前在ECMAScript中使用最廣泛椅野、認(rèn)同度最高的一種創(chuàng)建自定義類型的方法终畅。

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

function Person(name,age,job){

this.name = name;

this.age = age;

this.job = job;

this.friends = ["Shelby","Court"];

}

Person.prototype = [

constructor : Person,

sayName : function(){

alert(this.name);

}

}

varperson1 = new Person("Nicholas",29,"Software Engineer");

varperson2 = new Person("Greg",29,"Doctor");

person1.friends.push("Van");

alert(person1.friends === person2.friends);//false

alert(person1.sayName === person2.sayName);//true

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

4、原型鏈

原型鏈:ECMAScript中描述了原型鏈的概念竟闪,并將原型鏈作為實(shí)現(xiàn)繼承的主要方法离福。其基本思想是利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法。簡單回顧一下構(gòu)造函數(shù)炼蛤、原型妖爷、實(shí)例的關(guān)系:每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象,原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針理朋,而實(shí)例都包含一個(gè)指向原型對(duì)象的內(nèi)部指針絮识。那么,假如我們讓原型對(duì)象等于另一個(gè)類型的實(shí)例嗽上,結(jié)果會(huì)怎么樣呢次舌?顯然,此時(shí)的原型對(duì)象將包含一個(gè)指向另一個(gè)原型的指針兽愤,相應(yīng)地彼念,另一個(gè)原型中也包含著一個(gè)指向另一個(gè)構(gòu)造函數(shù)的指針挪圾。假如另一個(gè)原型又是另一個(gè)類型的實(shí)例,那么上述關(guān)系依然成立逐沙,如此層層遞進(jìn)哲思,就構(gòu)成了實(shí)例與原型的鏈條。這就是所謂原型鏈的基本概念吩案。

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

function SuperType(){

this.property = true;

}

SuperType.prototype.getSuperValue = ?function(){

return this.property;

};

functionSubType(){

this.subproperty = false;

}

SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function(){

return this.subproperty;

};

varinstance = new SubType();

alert(instance.getSuperValue());//true

alert(instance instanceof Object);//true

alert(instance instanceof SuperType);//true

alert(instance instanceof SubType);//true

alert(Object.prototype.isPrototypeOf(instance));//true

alert(SuperType.prototype.isPrototypeOf(instance));//true

alert(SubType.prototype.isPrototypeOf(instance));//true

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image003.jpg

子類型有時(shí)候需要重寫超類型中的某個(gè)方法也殖,或者需要添加超類型中不存在的某個(gè)方法。給原型添加方法的代碼一定要放在替換原型的語句之后务热。還有一點(diǎn)需要注意的是忆嗜,通過原型鏈實(shí)現(xiàn)繼承時(shí),不能使用對(duì)象字面量創(chuàng)建原型方法崎岂。因?yàn)檫@樣做就會(huì)重寫原型鏈捆毫。

原型鏈的問題:1、包含引用類型值的原型會(huì)被所有實(shí)例共享冲甘;2绩卤、不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)。實(shí)踐中很少會(huì)單獨(dú)使用原型鏈江醇。

5濒憋、組合繼承

組合繼承,指的是將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合到一塊陶夜,從而發(fā)揮二者之長的一種繼承模式凛驮。其背后的思路是使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,而通過借用構(gòu)造函數(shù)來實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承条辟。這樣黔夭,既通過在原型上定義方法實(shí)現(xiàn)了函數(shù)復(fù)用,又能夠保證每個(gè)實(shí)例都有它自己的屬性羽嫡。

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

function SuperType(name){

this.name = name;

this.colors = ["red","blue","green"];

}

SuperType.prototype.sayName = function(){

alert(this.name);

};

functionSubType(name,age){

SuperType.call(this,name);

this.age = age;

}

//繼承方法

SubType.prototype = new SuperType();

SubType.prototype.sayAge = function(){

alert(this.age);

};

varinstance1 = new SubType("Nicholas",29);

instance1.colors.push("black");

alert(instance1.colors);//"red,blue,green,black"

instance1.sayName();//"Nicholas";

instance1.sayAge();//29

varinstance2 = new SubType("Greg",27);

alert(instance2.colors);//"red,blue,green"

instance2.sayName();//"Greg";

instance2.sayAge();//27

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

組合繼承成為javascript中最常用的繼承模式本姥,而且,instanceof()杭棵、isPrototypeOf()也能夠用于識(shí)別給予組合繼承創(chuàng)建的對(duì)象婚惫。

6、原型式繼承

道格拉斯克羅克福德2006年寫了一篇文章魂爪,介紹了一種實(shí)現(xiàn)繼承的方法先舷,這種方法沒有使用嚴(yán)格意義上的構(gòu)造函數(shù)。他得想法是借助原型可以基于已有得對(duì)象創(chuàng)建新對(duì)象甫窟,同時(shí)還不必因此創(chuàng)建自定義類型密浑。為了達(dá)到這個(gè)目的,他給出了如下函數(shù):

function object(o){

function F(){}

F.prototype = o;

return new F();

}

在object()函數(shù)內(nèi)部粗井,先創(chuàng)建了一個(gè)臨時(shí)性的構(gòu)造函數(shù),然后將傳入的對(duì)象作為這個(gè)構(gòu)造函數(shù)的原型,最后返回了這個(gè)零食類型的一個(gè)新實(shí)例浇衬。從本質(zhì)上講懒构,object()對(duì)傳入其中的對(duì)象執(zhí)行了一次淺復(fù)制≡爬蓿看下面的例子:

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

var person = {

name : "Nicholas",

friends:["Shelby","Court","Van"]

};

varanotherPerson = object(person);

anotherPerson.name = "Greg";

anotherPerson.friends.push("Rob");

varyetAnotherPerson = object(person);

yetAnotherPerson.name = "Linda";

yetAnotherPerson.friends.push("Barbie");

alert(person.friends);//"Shelby,Court,Van,Rob,Barbie"

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

7胆剧、寄生式繼承

寄生式繼承時(shí)與原型式繼承緊密相關(guān)的一種思路,同樣由克羅克福德推出的醉冤。寄生式繼承的思路與寄生構(gòu)造函數(shù)和工廠模式類似秩霍,即創(chuàng)建一個(gè)僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部以某種方式來增強(qiáng)對(duì)象蚁阳,最后再像真地是它做了所有工作一樣返回對(duì)象铃绒。

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

function createAnother(original){

var clone = object(original);//通過調(diào)用函數(shù)創(chuàng)建一個(gè)新對(duì)象

clone.sayHi = function(){//以某種方式增強(qiáng)這個(gè)對(duì)象

alert("hi");

};

return clone;//返回這個(gè)對(duì)象

}

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]


更多學(xué)習(xí)分享加群 ? ? ?105601600

8、寄生組合式繼承

前面說過螺捐,組合繼承是javascript最常用的繼承模式颠悬,不過,它也有自己的不足定血。組合繼承最大的問題就是無論什么情況下赔癌,都會(huì)調(diào)用兩次超類型構(gòu)造函數(shù):一次是再創(chuàng)建子類型原型的時(shí)候,另一次是在子類型構(gòu)造函數(shù)內(nèi)部澜沟。沒錯(cuò)灾票,子類型最終會(huì)包含超類型對(duì)象的全部實(shí)例屬性,但我們不得不在調(diào)用子類型構(gòu)造函數(shù)時(shí)重寫這些屬性茫虽。再來看一看下面組合繼承的例子:

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

function SuperType(name){

this.name = name;

this.colors = ["red","blue","green"];

}

SuperType.prototype.sayName = function(){

alert(this.name);

};

functionSubType(name,age){

SuperType.call(this.name);//第二次調(diào)用SuperType()

this.age = age;

}

SubType.prototype = new SuperType();//第一次調(diào)用SuperType()

SubType.prototype.sayAge = function(){

alert(this.age);

};

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

第一次調(diào)用SuperType構(gòu)造函數(shù)時(shí)铝条,SubType.prototype會(huì)得到兩個(gè)屬性:name和colors,它們都是SuperType的實(shí)例屬性席噩,只不過現(xiàn)在位于SubType的原型中班缰。當(dāng)調(diào)用SubType構(gòu)造函數(shù)時(shí),又會(huì)調(diào)用一次SuperType構(gòu)造函數(shù)悼枢,這一次又在新對(duì)象上創(chuàng)建了實(shí)例屬性name和colors埠忘。于是,這兩個(gè)屬性就屏蔽了原型中的兩個(gè)同名屬性馒索。

file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg

圖中莹妒,有兩組name和colors屬性:一組在實(shí)例上,一組在SubType原型中绰上。這就是調(diào)用兩次SuperType構(gòu)造函數(shù)的結(jié)果旨怠。好在我們已經(jīng)找到了解決這個(gè)問題方法——寄生組合式繼承。所謂寄生組合式繼承蜈块,即通過借用構(gòu)造函數(shù)來繼承屬性鉴腻,通過原型鏈的混成行駛來繼承方法迷扇。其背后的基本思想是:不必為了制定子類型的原型而調(diào)用超類型的構(gòu)造函數(shù),我們所需要的無非就是超類型原型的一個(gè)副本而已爽哎。本質(zhì)上蜓席,就是使用寄生式繼承來繼承超類型的原型,然后再將結(jié)果指定給子類型的原型课锌。寄生組合式繼承的基本模式如下所示:

function inheritPrototype(subType,superType){

var prototype = object(superType.prototype);//創(chuàng)建對(duì)象

prototype.constructor = subType;//增強(qiáng)對(duì)象

subType.prototype = prototype;//指定對(duì)象

}

這個(gè)示例中的inheritPrototype()接收兩個(gè)參數(shù):子類型構(gòu)造函數(shù)和超類型構(gòu)造函數(shù)厨内。在函數(shù)內(nèi)部,第一步是創(chuàng)建超類型原型的一個(gè)副本渺贤。第二步是為創(chuàng)建的副本添加constructor屬性雏胃,從而彌補(bǔ)因重寫原型而失去的默認(rèn)的constructor屬性。最后一步志鞍,將新創(chuàng)建的對(duì)象(即副本)賦值給子類型的原型瞭亮。這樣,我們就可以調(diào)用inheritPrototype()函數(shù)的語句述雾,去替換前面例子中為子類型原型賦值的語句了街州。

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

function SuperType(name){

this.name = name;

this.colors = ["red","blue","green"];

}

SuperType.prototype.sayName = functon(){

alert(this.name);

};

functionSubType(name,age){

SuperType.call(this,name);

this.age = age;

}

inheritPrototype(SubType,SuperType);

SubType.prototype.sayAge = function(){

alert(this.age);

};

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

這個(gè)例子的高效率體現(xiàn)在它只調(diào)用了一次SuperType構(gòu)造函數(shù),并且因此避免了在SubType.prototype上面創(chuàng)建不必要的玻孟,多余的屬性唆缴。于此同時(shí),原型鏈還能保持不變黍翎,因此面徽,還能夠正常使用instanceof和isPrototypeOf()。開發(fā)人員普遍認(rèn)為寄生組合式繼承時(shí)引用類型最理想的繼承范式匣掸。在雅虎的YUI框架的YAHOO.lang.extend()中趟紊,實(shí)現(xiàn)了寄生調(diào)用繼承。

下面是寄生組合式繼承的一個(gè)完整的例子:

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

function object(o) {

function F(){}

F.prototype = o;

return new F();

}

functioninheritPrototype(subC, superC) {

var prototype = object(superC.prototype); //創(chuàng)建對(duì)象

prototype.constructor = subC; //增強(qiáng)對(duì)象

subC.prototype = prototype; //指定對(duì)象

}

varBaseClass = function() {

this.className = "Base";

};

BaseClass.prototype = {

showName: function() {

alert(this.className);

}

};

varSubClass = function() {

BaseClass.call(this);

this.classDesc = "SubClass";

};

inheritPrototype(SubClass, BaseClass);

SubClass.prototype.showDesc = function() {

alert(this.classDesc);

};

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

9碰酝、拷貝組合式繼承

這個(gè)繼承模式是來自博客園的村長趙大寶的一篇文章——《尋求完美之javascript繼承》霎匈。改造的實(shí)質(zhì)就是拋棄使用父類原型副本重寫子類原型的做法。這種方式不僅兼顧了效率送爸、繼承實(shí)現(xiàn)铛嘱、多態(tài),而且不創(chuàng)建父類原型副本袭厂,即不發(fā)生原型的重寫墨吓,避免了寄生組合繼承存在的缺陷。另外纹磺,拷貝組合繼承顯而易見的對(duì)多重繼承的實(shí)現(xiàn)提供了更優(yōu)的支持帖烘。

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

function extend(subC, baseC) {

for (var ptototypeName in baseC.prototype) {

if (typeof(subC.prototype[ptototypeName])=== 'undefined') {

subC.prototype[ptototypeName]= baseC.prototype[ptototypeName]; //原型屬性的拷貝

}

}

subC.prototype.constructor = subC; //增強(qiáng)

}

varBaseClass = function() {

this.className = "Base";

};

BaseClass.prototype = {

showName: function() {

alert(this.className);

}

};

varSubClass = function() {

BaseClass.call(this); //只執(zhí)行一次父類構(gòu)造函數(shù)

this.classDesc ="SubClass";

};

SubClass.prototype = {

showDesc: function() {

alert(this.classDesc);

}

};

extend(SubClass, BaseClass); //不破壞子類原型鏈的位置二

[url=]file:///C:/Users/i037145/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gif[/url]

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市橄杨,隨后出現(xiàn)的幾起案子秘症,更是在濱河造成了極大的恐慌照卦,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件历极,死亡現(xiàn)場(chǎng)離奇詭異窄瘟,居然都是意外死亡衷佃,警方通過查閱死者的電腦和手機(jī)趟卸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氏义,“玉大人锄列,你說我怎么就攤上這事」哂疲” “怎么了邻邮?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長克婶。 經(jīng)常有香客問我筒严,道長,這世上最難降的妖魔是什么情萤? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任鸭蛙,我火速辦了婚禮,結(jié)果婚禮上筋岛,老公的妹妹穿的比我還像新娘娶视。我一直安慰自己,他們只是感情好睁宰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布肪获。 她就那樣靜靜地躺著,像睡著了一般柒傻。 火紅的嫁衣襯著肌膚如雪孝赫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天红符,我揣著相機(jī)與錄音青柄,去河邊找鬼。 笑死违孝,一個(gè)胖子當(dāng)著我的面吹牛刹前,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播雌桑,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼喇喉,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了校坑?” 一聲冷哼從身側(cè)響起拣技,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤千诬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后膏斤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體徐绑,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年莫辨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了傲茄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡沮榜,死狀恐怖盘榨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蟆融,我是刑警寧澤草巡,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站型酥,受9級(jí)特大地震影響山憨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜弥喉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一郁竟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧档桃,春花似錦枪孩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嘹屯,卻和暖如春攻询,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背州弟。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國打工钧栖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人婆翔。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓拯杠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親啃奴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子潭陪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容