摘要:實(shí)現(xiàn)原型鏈的方式如下讓原型對(duì)象稱為另一個(gè)構(gòu)造函數(shù)的實(shí)例這個(gè)實(shí)例繼承了的屬性上述代碼繼承是通過(guò)來(lái)實(shí)現(xiàn),創(chuàng)建的實(shí)例,并將該實(shí)例賦給。無(wú)疑,集兩者之大成,這才是最常用的繼承模式。
原型鏈
JavaScript的繼承主要依靠原型鏈來(lái)實(shí)現(xiàn)的。我們知道,構(gòu)造函數(shù),原型,和實(shí)例之間的關(guān)系:每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象,原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針,而實(shí)例都包含一個(gè)原型對(duì)象的指針。
實(shí)現(xiàn)原型鏈的方式如下
function SuperType(){ this.property=true; } SuperType.prototype.getSuperValue=function(){ return this.property; }; function SubType(){ this.subpropertype=false; } //讓原型對(duì)象稱為另一個(gè)構(gòu)造函數(shù)的實(shí)例 SubType.prototype=new SuperType(); SubType.prototype.getSubValue=function(){ return this.subpropertype; }; var instance=new SubType(); alert(instance.getSuperValue());//true //這個(gè)實(shí)例繼承了SuperType.prototype的constructor屬性? alert(instance.constructor==SuperType);//true
上述代碼繼承是通過(guò)SubType.prototype=new SuperType();來(lái)實(shí)現(xiàn),創(chuàng)建SuperType的實(shí)例,并將該實(shí)例賦給SubType.prototype。
繼承實(shí)現(xiàn)的本質(zhì)是重寫原型對(duì)象,代之以一個(gè)新類型的實(shí)例。
下圖為構(gòu)造函數(shù),實(shí)例以及原型之間的關(guān)系圖:
圖片描述
原型鏈缺點(diǎn)原型鏈頂端:所有引用類型都默認(rèn)繼承Object,所以,所有函數(shù)的默認(rèn)原型都是Object的實(shí)例,默認(rèn)原型都會(huì)包含一個(gè)內(nèi)部指針[[prototype]],指向Object.prototype。
實(shí)例屬性變?yōu)樵蛯傩?/p>
function SuperType(){ this.color=["red","green","blue"]; } function SubType(){ } SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.color.push("black"); alert(instance1.color);//"red,green,blue,black" var instance2 = new SubType(); alert(instance2.color);//"red,green,blue,black"
這個(gè)問(wèn)題似曾相識(shí),正是原型模式創(chuàng)建對(duì)象時(shí)由于共享引用類型屬性,導(dǎo)致牽一發(fā)動(dòng)全身的問(wèn)題。
在創(chuàng)建子類型時(shí),不能向超類型的構(gòu)造函數(shù)傳遞參數(shù)。
所以,多帶帶使用原型鏈情況較少。
借用構(gòu)造函數(shù)針對(duì)原型鏈的第一個(gè)問(wèn)題,我們可采用借用構(gòu)造函數(shù)的技術(shù)來(lái)解決。基本思想就是在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)。看例子:
function SuperType(){ this.color=["red","green","blue"]; } function SubType(){ //繼承自SuperType SuperType.call(this); } var instance1 = new SubType(); instance1.color.push("black"); alert(instance1.color);//"red,green,blue,black" var instance2 = new SubType(); alert(instance2.color);//"red,green,blue"
在新創(chuàng)建的SubType子類型的實(shí)例中調(diào)用SuperType超類型構(gòu)造函數(shù),就可以在新的實(shí)例對(duì)象上執(zhí)行SuperType()函數(shù)中定義的所有對(duì)象初始化代碼。問(wèn)題不就解決了嗎!
但是,這種模式的缺點(diǎn)是在超類型中定義的方法,對(duì)子類型是不可見(jiàn)的,無(wú)法實(shí)現(xiàn)共享方法。
所以,這種方法也不常用。
組合上述兩種方法就是組合繼承。用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,用借用構(gòu)造函數(shù)技術(shù)來(lái)實(shí)現(xiàn)實(shí)例屬性的繼承。無(wú)疑,集兩者之大成,這才是最常用的繼承模式。看:
function SuperType(){ this.name=name; this.color=["red","green","blue"]; } SuperType.prototype.sayName = function(){ alert(this.name); } function SubType(name,age){ //繼承了SuperType SuperType.call(this,name); //自己又添加了一個(gè) this.age = age; } //構(gòu)建原型鏈 SubType.prototype = new SuperType(); //重寫SubType.prototype的constructor屬性,指向自己的構(gòu)造函數(shù)SubType SubType.prototype.constructor=SubType; //原型方法,被實(shí)例們共享 SubType.prototype.sayAge = function(){ alert(this.age); } var instance1 = new SubType("Nichola",29); instance1.color.push("black"); alert(instance1.color);//"red,green,blue,black" instance1.sayName();//"Nichola" instance1.sayAge();//29 var instance2 = new SubType("Grey",24); alert(instance2.color);//"red,green,blue" instance2.sayAge();//24 instance2.sayName();//"Grey"
這個(gè)方案已經(jīng)看似perfect了。但是,后面再說(shuō)。
原型式繼承借助原型可以基于已有的對(duì)象創(chuàng)建新的對(duì)象,不必因此創(chuàng)建自定義類型。
function object(o){ //返回一個(gè)對(duì)象以傳入對(duì)象為原型 function F(){} F.prototype = o; return new F(); } var person ={ name:"Nichola", friends:["Shelly","Court","Van"] }; var person1 = object(person); person1.name = "Grey"; person1.friends.push("Rob"); var person2 = object(person); person2.name = "Linda"; person2.friends.push("Barble"); alert(person.friends);//"Shelly,Court,Van,Grey,Barble"
使用場(chǎng)合:需求簡(jiǎn)單,只需要讓新對(duì)象與已有對(duì)象保持相似。優(yōu)點(diǎn),不必創(chuàng)建構(gòu)造函數(shù),缺點(diǎn),包含引用類型值的屬性始終共享相應(yīng)的值。
Object.create()正是為實(shí)現(xiàn)這種模式誕生。
與原型式繼承相似,也是基于某個(gè)對(duì)象或某些信息創(chuàng)建對(duì)象,然后增強(qiáng)對(duì)象,最后返回對(duì)象。實(shí)現(xiàn)方法:創(chuàng)建一個(gè)僅用于封裝繼承過(guò)程的函數(shù),該函數(shù)在內(nèi)部以某種方式來(lái)增強(qiáng)對(duì)象,最后返回這個(gè)對(duì)象。看!
function createAnother(original){ var clone = object(original);//通過(guò)調(diào)用函數(shù)創(chuàng)建對(duì)象 clone.sayHi= function (){ //增強(qiáng)對(duì)象 alert("Hi"); }; return clone;//返回對(duì)象 } //可以返回新對(duì)象的函數(shù) function object(o){ function F(){} F.prototype = o; return new F(); } var person ={ name:"Nichola", friends:["Shelly","Court","Van"] }; var anotherPerson = createAnother(person); anotherPerson.sayHi();//"Hi"
這種繼承模式適用的場(chǎng)合:任何返回新對(duì)象的函數(shù)都可以。缺點(diǎn)是不能做到函數(shù)復(fù)用。
寄生組合式繼承上面說(shuō)到組合繼承也有缺點(diǎn),就是無(wú)論在何種情況下,都會(huì)調(diào)用兩次超類型構(gòu)造函數(shù),一次是在創(chuàng)建子類型原型時(shí),還有一次是在子類型構(gòu)造函數(shù)內(nèi)部。
這種模式集中了寄生式和組合式繼承的優(yōu)點(diǎn)。
function SuperType(){ this.name=name; this.color=["red","green","blue"]; } function SubType(){ //第二次調(diào)用SuperType() SuperType.call(this,name); this.age = age; } //第一次調(diào)用SuperType() SubType.prototype = new SuperType(); SubType.prototype.constructor=SubType; SubType.prototype.sayAge = function(){ alert(this.age); } var instance1 = new SubType("Nichola",29);
第一次調(diào)用SuperType():給SubType.prototype寫入兩個(gè)屬性name,color
第二次調(diào)用SuperType():給instance1寫入兩個(gè)屬性name,color
實(shí)例對(duì)象instance1上的兩個(gè)屬性就屏蔽了其原型對(duì)象SubType.prototype的兩個(gè)同名屬性。所以,組合模式的缺點(diǎn)就是在SubType.prototype上創(chuàng)建不必要的重復(fù)的屬性。
寄生組合式繼承基本模式:
function inheritPrototype(SubType,SuperType){ var prototype = object(superType.prototype);//創(chuàng)建對(duì)象 prototype.constructor = SubType;//增強(qiáng)對(duì)象 SubType.prototype = prototype;//制定對(duì)象 }
首先,創(chuàng)建超類型的一個(gè)副本;
其次,為副本添加constructor屬性,使其指向子類型構(gòu)造函數(shù);
最后,將副本賦值給子類型原型。
function SuperType(){ this.name=name; this.color=["red","green","blue"]; } function SubType(){ SuperType.call(this.name); this.age = age; } function inheritPrototype(SubType,SuperType){ var prototype = object(superType.prototype);//創(chuàng)建對(duì)象 prototype.constructor = SubType;//增強(qiáng)對(duì)象 SubType.prototype = prototype;//制定對(duì)象 } SubType.prototype.sayAge = function(){ alert(this.age); } var instance1 = new SubType("Nichola",29);
借用構(gòu)造函數(shù)來(lái)繼承實(shí)例屬性,使用寄生式繼承來(lái)繼承超類型的原型,然后再將結(jié)果賦給子類型原型。這樣既可以繼承超類型的實(shí)例屬性,也可繼承超類型原型中的原型屬性。這是最優(yōu)解。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/80889.html
摘要:繼承的是超類型中構(gòu)造函數(shù)中的屬性,如上繼承了屬性,但沒(méi)有繼承原型中的方法。上述造成的結(jié)果是子類型實(shí)例中有兩組超類型的構(gòu)造函數(shù)中定義的屬性,一組在子類型的實(shí)例中,一組在子類型實(shí)例的原型中。 ECMAScript只支持實(shí)現(xiàn)繼承,主要依靠原型鏈來(lái)實(shí)現(xiàn)。與實(shí)現(xiàn)繼承對(duì)應(yīng)的是接口繼承,由于script中函數(shù)沒(méi)有簽名,所以無(wú)法實(shí)現(xiàn)接口繼承。 一、原型鏈 基本思想:利用原型讓一個(gè)引用類型繼承另一個(gè)引用...
摘要:繼承和前面兩篇文章中的知識(shí)非常相關(guān),如果對(duì)函數(shù)創(chuàng)建原理和原型鏈不熟悉,請(qǐng)猛戳高級(jí)程序設(shè)計(jì)筆記創(chuàng)建對(duì)象高級(jí)程序設(shè)計(jì)筆記原型圖解繼承,通俗的說(shuō),就是將自身不存在的屬性或方法,通過(guò)某種方式為自己所用文章分別介紹原型鏈繼承繼承借用構(gòu)造函數(shù)繼承組合繼 繼承和前面兩篇文章中的知識(shí)非常相關(guān),如果對(duì)函數(shù)創(chuàng)建原理和原型鏈不熟悉,請(qǐng)猛戳:《javascript高級(jí)程序設(shè)計(jì)》筆記:創(chuàng)建對(duì)象《javascri...
摘要:深入之繼承的多種方式和優(yōu)缺點(diǎn)深入系列第十五篇,講解各種繼承方式和優(yōu)缺點(diǎn)。對(duì)于解釋型語(yǔ)言例如來(lái)說(shuō),通過(guò)詞法分析語(yǔ)法分析語(yǔ)法樹,就可以開始解釋執(zhí)行了。 JavaScript深入之繼承的多種方式和優(yōu)缺點(diǎn) JavaScript深入系列第十五篇,講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 寫在前面 本文講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 但是注意: 這篇文章更像是筆記,哎,再讓我...
摘要:此時(shí)的原型對(duì)象包括一個(gè)指向另一個(gè)原型的指針,相應(yīng)的,另一個(gè)原型中的指向另一個(gè)構(gòu)造函數(shù)。這種關(guān)系層層遞進(jìn),就通過(guò)一個(gè)原型對(duì)象鏈接另一個(gè)構(gòu)造函數(shù)的原型對(duì)象的方式實(shí)現(xiàn)了繼承。 讀這篇之前,最好是已讀過(guò)我前面的關(guān)于對(duì)象的理解和封裝類的筆記。第6章我一共寫了3篇總結(jié),下面是相關(guān)鏈接:讀《javaScript高級(jí)程序設(shè)計(jì)-第6章》之理解對(duì)象讀《javaScript高級(jí)程序設(shè)計(jì)-第6章》之封裝類 一...
摘要:探討判斷橫豎屏的最佳實(shí)現(xiàn)前端掘金在移動(dòng)端,判斷橫豎屏的場(chǎng)景并不少見(jiàn),比如根據(jù)橫豎屏以不同的樣式來(lái)適配,抑或是提醒用戶切換為豎屏以保持良好的用戶體驗(yàn)。 探討判斷橫豎屏的最佳實(shí)現(xiàn) - 前端 - 掘金在移動(dòng)端,判斷橫豎屏的場(chǎng)景并不少見(jiàn),比如根據(jù)橫豎屏以不同的樣式來(lái)適配,抑或是提醒用戶切換為豎屏以保持良好的用戶體驗(yàn)。 判斷橫豎屏的實(shí)現(xiàn)方法多種多樣,本文就此來(lái)探討下目前有哪些實(shí)現(xiàn)方法以及其中的優(yōu)...
閱讀 2958·2021-11-08 13:20
閱讀 1031·2021-09-22 15:20
閱讀 660·2019-08-30 15:53
閱讀 1964·2019-08-30 15:43
閱讀 1278·2019-08-29 17:21
閱讀 540·2019-08-29 12:15
閱讀 2375·2019-08-28 17:51
閱讀 3142·2019-08-26 13:26