摘要:簡單回顧一下構造函數原型和實例對象之間的關系每個構造函數都有一個原型對象。找到生成構造函數的原型對象的構造函數,搜索其原型對象,找到了。
JS面向對象的程序設計之繼承的實現 - 原型鏈
前言:最近在細讀Javascript高級程序設計,對于我而言,中文版,書中很多地方翻譯的差強人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯誤,會非常感謝您的指出。文中絕大部分內容引用自《JavaScript高級程序設計第三版》。
繼承是OO(Object Oriented, 面向對象)語言中的一個最為人津津樂道的概念。
許多OO語言都支持兩種繼承方式:接口繼承和實現繼承。
接口繼承只繼承簽名,而實現繼承則繼承實際的方法。
如前所述, 由于函數沒有簽名,在ECMAScript中無法實現接口繼承。
前面暫時看不懂沒關系,可以學學一些Java基礎知識,這樣回過來看,就明白說啥了!!
記住這句就行,ECMAScript只支持實現繼承,而且其實現繼承主要是依靠原型鏈來實現的。
原型鏈ECMAScript中描述了原型鏈的概念,并將原型鏈作為實現繼承的主要方法。
其基本思想是利用原型,讓一個引用類型繼承另一個引用類型的屬性和方法。
簡單回顧一下構造函數、原型和實例對象之間的關系:
每個構造函數都有一個原型對象。
原型對象都包含一個指向構造函數的指針。
實例對象都包含一個指向原型對象的內部指針。
//偽代碼 //構造函數 function Person(){ } //構造函數的原型對象中constructor指向構造函數自身 Person.prototype.constructor => 指向 function Person(){} var person1 = new Person(); //實例對象指向原型對象的內部指針。 person1.__proto__ => 指向 Person.prototype
這部分,文字描述有些晦澀!看不懂的話,先看代碼例子。
假如,我們讓原型對象等于另一個類型的實例對象, 結果會怎么樣呢?
顯然,此時原型對象將包含一個指向另一個原型的指針。
相應地, 另一個原型中也包含著一個指向另一個構造函數原型的指針。
假如,另一個原型又是另一個類型的實例對象,還是包含一個指針指向另外一個構造函數的原型,所以上述關系依然成立。
如此層層遞進,就構成了實例與原型的鏈條。
這就是所謂原型鏈的基本概念。
你可以想象成 “不斷認祖歸宗”的過程,認祖歸宗的路徑連接起來,就形成了一個“血緣鏈”。
實現原型鏈的基本模式
//實現原型鏈的示例代碼 //SuperType 父類型 function SuperType(){ this.property = true; } SuperType.prototype.getSuperProperty = function() { console.log(this.property); return this.property; } //SubType 子類型 function SubType() { this.subproperty = false; } //子類型 繼承 父類型 SubType.prototype = new SuperType(); //實際上子類型的原型是這樣的。 /*SubType.prototype = { property: true, __proto__: { constructor : SuperType, getSuperProperty:function() { console.log(this.property); return this.property; } } } */ SubType.prototype.getSubProperty = function(){ console.log(this.subproperty); return this.subproperty; } //那么現在子類型的原型對象是這樣的 /*SubType.prototype = { property: true, getSubProperty: function() { console.log(this.subproperty); return this.subproperty; }, __proto__: { constructor : SuperType, getSuperProperty:function() { console.log(this.property); return this.property; } } } */ var subInstanceObject = new SubType(); console.log(subInstanceObject.getSuperProperty()); // true
以上代碼定義了兩個類型(構造函數):
SuperType(父類型)和 SubType(子類型)。
每個類型分別有一個屬性和方法。
它們主要的區別是SubType繼承了SuperType(子類繼承父類),而繼承是通過創建SuperType的實例對象, 然后將實例對象賦予SubType.prototype(子類的原型)實現的。
實現的本質是重寫原型,改寫為另外一個類型的實例對象,
生成另外一個類型的實例對象的過程中,實例對象中的所有屬性和方法,賦予給重寫的原型,
重點,這個實例對象的內部有個屬性__proto__指向,構造這個實例對象的構造函數原型,
從而實現繼承,
屬性__proto__,確實很像一條鏈子!
實現原型鏈,本質上擴展了原型搜索機制。
當讀取或者訪問一個實例屬性時,首先會在實例中搜索該屬性,如果沒有找到該屬性,則會沿著去搜索實例對象內部的__proto__指向的原型。
通過原型鏈實現繼承,搜索過程,就像沿著一條鏈子不斷向上搜尋。
就上面的示例代碼來說,subInstanceObject.getSuperProperty()會經歷三次查找!
查找過程
搜索實例對象自身, 沒找到該方法,沿著__proto__找。
找到(構造)實例對象的構造函數的原型對象,還是沒找到該方法,繼續沿著原型對象的__proto__的指向尋找。
找到生成構造函數的原型對象的構造函數,搜索其原型對象,找到了。
在找不到屬性或方法的情況下,搜索過程總是要一環一環地前行到原型鏈末端才會停下來。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/98387.html
摘要:第一種方式是使用操作符,只要檢測的實例對象中的原型鏈包含出現過的構造函數,結果就會返回。而這也正是組合使用原型模式和構造函數模式的原因。在構造函數模式中定義屬性,在原型模式中定義共享的方法。 前言:最近在細讀Javascript高級程序設計,對于我而言,中文版,書中很多地方翻譯的差強人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯誤,會非常感謝您的指出。文中絕大部分內容引用自《Ja...
摘要:是完全的面向對象語言,它們通過類的形式組織函數和變量,使之不能脫離對象存在。而在基于原型的面向對象方式中,對象則是依靠構造器利用原型構造出來的。 JavaScript 函數式腳本語言特性以及其看似隨意的編寫風格,導致長期以來人們對這一門語言的誤解,即認為 JavaScript 不是一門面向對象的語言,或者只是部分具備一些面向對象的特征。本文將回歸面向對象本意,從對語言感悟的角度闡述為什...
摘要:面向對象之二原型鏈對象和對象之間的關系注意這個系列文章要經常站在之父的視角去思考。思考問題我們都知道都屬于那么既然他們都是對象一定有某些相同之處吧對象和對象之間有什么關聯呢如果說你沒有思考過這個問題那么可以換一個更具體的問題。 JS面向對象之二 【原型鏈】(對象和對象之間的關系) 注意這個系列文章,要經常站在JS之父的視角去思考。 牢記我們的需求,我要在JS沒有class的情況下,那么...
摘要:實現思路使用原型鏈實現對原型方法和方法的繼承,而通過借用構造函數來實現對實例屬性的繼承。繼承屬性繼承方法以上代碼,構造函數定義了兩個屬性和。 JS面向對象的程序設計之繼承的實現-組合繼承 前言:最近在細讀Javascript高級程序設計,對于我而言,中文版,書中很多地方翻譯的差強人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯誤,會非常感謝您的指出。文中絕大部分內容引用自《Java...
摘要:很多情況下,通常一個人類,即創建了一個具體的對象。對象就是數據,對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
閱讀 2639·2021-11-22 15:24
閱讀 1370·2021-11-17 09:38
閱讀 2746·2021-10-09 09:57
閱讀 1192·2019-08-30 15:44
閱讀 2438·2019-08-30 14:00
閱讀 3538·2019-08-30 11:26
閱讀 2935·2019-08-29 16:28
閱讀 746·2019-08-29 13:56