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