原型鏈之前一直都不是很理解,這兩天把《你不知道的JavaScript》和《JavaScript高級程序設計》的原型鏈那章看完后有所理解,在這里先記下來,加深印象。
什么是原型對象要講清楚什么是原型鏈需要從原型對象開始談,那么什么是原型對象呢?《JavaScript高級程序設計》中是這樣講的:
無論什么時候,只要創(chuàng)建了一個新函數(shù),就會根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個prototype屬性,這個屬性指向函數(shù)的原型對象。
簡單來說,原型對象也是對象,但是通過原型對象可以實現(xiàn)對象的屬性繼承。
這里用《JavaScript高級程序設計》這本書上的demo來解釋一下:
function Person () { } Person.prototype.name = "Nicholas" Person.prototype.age = 29 Person.prototype.job = "Software Engineer" Person.prototype.sayName = function () { console.log(this.name) } var person1 = new Person() var person2 = new Person()
這里聲明了一個Person函數(shù),沒有定義任何屬性;但是在Person的原型對象里定義了name,age,job屬性和sayName方法。之后創(chuàng)建了兩個Person的實例對象,person1和person2。在這里構(gòu)造函數(shù),原型對象,實例對象三者的關系用一張圖片表示就是
(圖片來源谷歌,侵刪)
如圖所示,Person的prototype指針指向它的原型對象,實例對象的[[Prototype]]指針也指向它的原型對象。這里簡單說明一下什么是[[Prototype]]指針:
調(diào)用構(gòu)造函數(shù)創(chuàng)建一個新實例之后,該實例的內(nèi)部將包含一個指針(內(nèi)部屬性),指向構(gòu)造函數(shù)的原型對象,這就是[[Prototype]]指針。
現(xiàn)在,person1和person2的[[Prototype]]都指向了Person.prototype,這樣的話Person.prototype里的方法和屬性是被person1和person2共用的。
如何證明他們共用Person.prototype里面的屬性和方法?請執(zhí)行下面的語句:
person1.sayName() // "Nicholas" person2.sayName() // "Nicholas"
有人說了,你這初始化的name屬性只有一個,執(zhí)行的結(jié)果當然都一樣啊。那么請再試試下面這句:
console.log(person1.sayName === person2.sayName) //true
結(jié)果很明顯,person1.sayName和person2.sayName指向的是同一個方法。到這里可能有人會疑惑:一開始的代碼中Person函數(shù)里并沒有定義任何屬性和方法,為什么person1和person2能執(zhí)行sayName方法?那么這就要來談談對象屬性調(diào)用的過程了。
以上面代碼為例,當你執(zhí)行person1.name時,解析器會開始查找person1中有沒有name屬性,如果找到了則返回屬性值;如果沒找到,則在person1的原型對象中繼續(xù)找,找到了則返回屬性值;如果還沒找到,就沿著原型鏈往上繼續(xù)找,如果最終還是沒找到就返回undefined。
到這里大家也明白了多個對象實例共享原型對象的屬性和方法的基本原理了,那么有人又會問了,如果我通過給實例對象屬性賦值能不能重寫原型對象里的屬性和方法呢?
答案是不行的,在實例對象中對原型對象中的同名屬性賦值會屏蔽原型對象中的屬性。簡單解釋就是,對person1中的name屬性賦值會直接在person1中添加name屬性。但是有兩種情況下,當name屬性不存在于person1中而存在于原型對象中時,直接給person1.name賦值會有不一樣事情發(fā)生:
1.當原型對象中的name屬性標記為只讀(writable: false)時,對name屬性的賦值不會在person1添加name屬性,也不會修改原型對象中的name屬性,在嚴格模式下還會報錯。
2.當原型對象中的name屬性是一個setter,那么對person1中的name屬性執(zhí)行賦值語句就會調(diào)用setter,但name不會被添加到person1中。
這部分如果不懂什么是只讀和setter,大家可以去看一下Object.defineProperty。
其實講到這里,原型對象是什么已經(jīng)基本清楚了。那么原型鏈就很簡單了,繼續(xù)上面的demo:
function Parent () { this.parentName = "noOne" } function Person () { this.name = "Nicholas" } Person.prototype = new Parent() var person1 = new Person()
這個例子中,我們把Parent的實例對象賦給了Person的原型對象。Person.prototype中的[[Prototype]]此時指向了Parent.prototype。舉一反三,Parent.prototype也可以是另一個原型的實例對象,這樣不斷地層層遞進便構(gòu)成了原型鏈。
原型鏈的主要作用便是實現(xiàn)繼承,這部分后續(xù)的文章我會繼續(xù)講。
本人經(jīng)驗尚淺,目前對于前端仍在不斷摸索和學習,文章如有錯誤,歡迎各位指正。最后附上本人博客地址和原文鏈接,希望能向各位多多學習。
lbj的前端之路
原文鏈接:學習JavaScript之原型鏈
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/91722.html
摘要:我們用一張圖表示構(gòu)造函數(shù)和實例原型之間的關系好了構(gòu)造函數(shù)和實例原型之間的關系我們已經(jīng)梳理清楚了,那我們怎么表示實例與實例原型,也就是或者和之間的關系呢。 開篇: 在Brendan Eich大神為JavaScript設計面向?qū)ο笙到y(tǒng)的時候,借鑒了Self 和Smalltalk這兩門基于原型的語言,之所以選擇基于原型的面向?qū)ο笙到y(tǒng),并不是因為時間匆忙,它設計起來相對簡單,而是因為從一開始B...
摘要:我們用一張圖表示構(gòu)造函數(shù)和實例原型之間的關系好了構(gòu)造函數(shù)和實例原型之間的關系我們已經(jīng)梳理清楚了,那我們怎么表示實例與實例原型,也就是或者和之間的關系呢。 開篇: 在Brendan Eich大神為JavaScript設計面向?qū)ο笙到y(tǒng)的時候,借鑒了Self 和Smalltalk這兩門基于原型的語言,之所以選擇基于原型的面向?qū)ο笙到y(tǒng),并不是因為時間匆忙,它設計起來相對簡單,而是因為從一開始B...
摘要:實現(xiàn)原型鏈的方式如下讓原型對象稱為另一個構(gòu)造函數(shù)的實例這個實例繼承了的屬性上述代碼繼承是通過來實現(xiàn),創(chuàng)建的實例,并將該實例賦給。無疑,集兩者之大成,這才是最常用的繼承模式。 原型鏈 JavaScript的繼承主要依靠原型鏈來實現(xiàn)的。我們知道,構(gòu)造函數(shù),原型,和實例之間的關系:每個構(gòu)造函數(shù)都有一個原型對象,原型對象都包含一個指向構(gòu)造函數(shù)的指針,而實例都包含一個原型對象的指針。 實現(xiàn)原型鏈...
摘要:除此之外,原型是共享的,如果我們有的寫法,改變這兩個對象任何一個的原型都會影響另外一個,這在大多的情況下是不可取的。當對象查找一個屬性的時候,他會沿著原型鏈一直往上追蹤,直到直到為之。在性能方面,原則上應該盡量避免原型鏈太長。 簡介 如果之間學習過cpp 、java 之類的語言,都會知道他們是可以基于類 class 進行繼承的, 在JavaScript 中,并沒有類繼承這個概念,要實...
摘要:深入系列的第一篇,從原型與原型鏈開始講起,如果你想知道構(gòu)造函數(shù)的實例的原型,原型的原型,原型的原型的原型是什么,就來看看這篇文章吧。讓我們用一張圖表示構(gòu)造函數(shù)和實例原型之間的關系在這張圖中我們用表示實例原型。 JavaScript深入系列的第一篇,從原型與原型鏈開始講起,如果你想知道構(gòu)造函數(shù)的實例的原型,原型的原型,原型的原型的原型是什么,就來看看這篇文章吧。 構(gòu)造函數(shù)創(chuàng)建對象 我們先...
閱讀 3011·2021-10-27 14:15
閱讀 2999·2021-09-07 10:18
閱讀 1320·2019-08-30 15:53
閱讀 1570·2019-08-26 18:18
閱讀 3373·2019-08-26 12:15
閱讀 3460·2019-08-26 10:43
閱讀 654·2019-08-23 16:43
閱讀 2207·2019-08-23 15:27