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