JavaScript原型鏈詳解
例子:
function Person(name,walk){
this.name=name
this.walk=walk
this.getName=function(){
console.log(this.name)
}
}
Person.eat=function(){console.log('eat')}
Person.prototype.getWalk=function(){console.log(this.walk)}
const person=new Person('張三','順拐')constructor
- 當(dāng)我們找實(shí)例的constructor的時(shí)候他自己本身是沒有的,所以會(huì)沿著原型鏈往上找,而他原型鏈的上一級(jí)是他構(gòu)造函數(shù)的prototype,這個(gè)有constructor,所以會(huì)被實(shí)例繼承,而這個(gè)constructor指向構(gòu)造函數(shù)本身,即person無constructor,他繼承Person.prototype的constructor,而
Person.prototype.constructor=Person,所以person.construtor=Person - 構(gòu)造函數(shù)本身也是一個(gè)對(duì)象,他作為對(duì)象的行為和實(shí)例也一樣,即Person作為對(duì)象的行為和person是一樣的,所以他也會(huì)繼承他的構(gòu)造函數(shù)的prototype的constructor,而所有的函數(shù)作為對(duì)象時(shí)的構(gòu)造函數(shù)均是Function,所以
Person.constructor=Function.prototype.constructor=Function
prototype(原型對(duì)象)與__proto__(對(duì)象原型,下面簡稱原型)
函數(shù)有一個(gè)對(duì)象屬性是prototype(只有函數(shù)有,普通對(duì)象是沒有的),注意箭頭函數(shù)沒有prototype,構(gòu)造函數(shù)也是函數(shù)所以也有prototype,這個(gè)屬性定義了構(gòu)造函數(shù)制造出來的對(duì)象的公共祖先,通過該構(gòu)造函數(shù)產(chǎn)生的對(duì)象可以繼承該原型的屬性和函數(shù),即person可以繼承Person.prototype上的函數(shù)
實(shí)例的原型都指向他的構(gòu)造函數(shù)的原型對(duì)象,即person的原型指向Person.prototype
所有的函數(shù)(包括箭頭函數(shù),箭頭函數(shù)只是沒有prototype而已,也就是不能構(gòu)造實(shí)例)的構(gòu)造函數(shù)都是Function,即所有的函數(shù)都是Function的實(shí)例,包括Object,因?yàn)镺bject本身也是構(gòu)造函數(shù),可以拿來構(gòu)造對(duì)象,所以任何函數(shù)的原型都指向Function.prototype,所以O(shè)bject的原型也指向Function.prototype,而Function是一個(gè)構(gòu)造函數(shù),所以Function自己也是由Function.prototype構(gòu)造的,即Function本身的原型也指向Function.prototype
普通對(duì)象是Object的實(shí)例,即由Object構(gòu)造的所以O(shè)bject是普通對(duì)象的構(gòu)造函數(shù),所以普通對(duì)象的原型為Object,注意,構(gòu)造函數(shù)是函數(shù),但是構(gòu)造函數(shù)的prototype本身是一個(gè)非函數(shù)對(duì)象,即Person.prototype和Function.prototype的原型都指向Object.prototype
而Object.prototype理論上來說也是對(duì)象那也應(yīng)該由Object.prototype構(gòu)造,但是為了避免循環(huán)所以O(shè)bject.prototype指向null
參考3,4可知原型鏈即對(duì)象的原型,原型的原型…,比如person的原型鏈為person=>Person.prototype=>Object.prototype=>null,并且要理解Person的原型鏈?zhǔn)?code>Person=>Function.prototype=>Object.prototype=>null,Function的原型鏈?zhǔn)?code>Function=>Function.prototype=>Object.prototype
注意,在構(gòu)造函數(shù)中寫this.屬性那構(gòu)造函數(shù)不會(huì)有這個(gè)屬性,因?yàn)檫@本質(zhì)上是一條語句而不是屬性,this是指向調(diào)用方的,所以實(shí)例中會(huì)有這個(gè)屬性,比如
function Person(){
this.name=15
}
const p=new Person()
console.log(p.name)//15
console.log(Person.name)//undefined
Person.prototype.name=20
console.log(p.name)//15,因?yàn)樵玩湉牡淄险业?/pre>一般像這種固定值的屬性沒必要放在Person中用this給實(shí)例定義,因?yàn)檫@樣一來每個(gè)實(shí)例都會(huì)創(chuàng)建一個(gè),不如直接放在原型上即Person.prototype.name=15這樣如何Person里不再定義this.name
如果修改Person.prototype的引用即Person.prototype={}有兩種情況,若實(shí)例是在修改前定義的那實(shí)例將無法連接到新的Person.prototype上,因?yàn)樗呀?jīng)連接到舊的上了,如果在修改后定義那就連接在新的上面,注意Person能否連接到新的上面取決于新的引用是否將constructor指回Person,永遠(yuǎn)記得Person.prototype也只是一個(gè)對(duì)象,他和Person的連接是通過上面的constructor對(duì)象屬性指向Person完成的,新對(duì)象如果直接沒定義constructor或者定義成別的那也連接不上Person
通過實(shí)例是無法修改構(gòu)造函數(shù)原型上的屬性的,比如如果person.name='李四’那這個(gè)是給perosn實(shí)例這個(gè)對(duì)象上添加了一個(gè)叫name的屬性而不是Person.prototype.name被修改了; delete person.name只能刪除person自己的name屬性不會(huì)刪除Person.prototype的name屬性,但是注意即使person上沒name這個(gè)也會(huì)返回true,這不代表Person.prototype的name屬性被刪除了,而是執(zhí)行刪除沒找到要?jiǎng)h除的也算刪除成功 ;
到此這篇關(guān)于JavaScript原型鏈詳解的文章就介紹到這了,更多相關(guān)js原型鏈內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在Postman的腳本中如何使用pm對(duì)象獲取接口的請(qǐng)求參數(shù)
這篇文章主要介紹了在Postman的腳本中如何使用pm對(duì)象獲取接口的請(qǐng)求參數(shù),本文通過實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09
javascript搜索自動(dòng)提示功能的實(shí)現(xiàn)
使用 jQuery(Ajax)/PHP/MySQL實(shí)現(xiàn)自動(dòng)完成功我覺得我有必要寫這個(gè)教程,因?yàn)樵?jīng)見到的大部分關(guān)于自動(dòng)完成的應(yīng)用程序都只是給你一個(gè)程序源碼包,然后告訴你怎么使用,而不是告訴你它是如何工作的以及為什么這樣做。2008-06-06
Javascript中async與await的捕捉錯(cuò)誤詳解
這篇文章主要為大家詳細(xì)介紹了Javascript中async與await的捕捉錯(cuò)誤,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03
JS 日期與時(shí)間戮相互轉(zhuǎn)化的簡單實(shí)例
下面小編就為大家?guī)硪黄狫S 日期與時(shí)間戮相互轉(zhuǎn)化的簡單實(shí)例。小編覺得挺不錯(cuò)的, 現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06

