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
- 當我們找實例的constructor的時候他自己本身是沒有的,所以會沿著原型鏈往上找,而他原型鏈的上一級是他構造函數(shù)的prototype,這個有constructor,所以會被實例繼承,而這個constructor指向構造函數(shù)本身,即person無constructor,他繼承Person.prototype的constructor,而
Person.prototype.constructor=Person,所以person.construtor=Person - 構造函數(shù)本身也是一個對象,他作為對象的行為和實例也一樣,即Person作為對象的行為和person是一樣的,所以他也會繼承他的構造函數(shù)的prototype的constructor,而所有的函數(shù)作為對象時的構造函數(shù)均是Function,所以
Person.constructor=Function.prototype.constructor=Function
prototype(原型對象)與__proto__(對象原型,下面簡稱原型)
函數(shù)有一個對象屬性是prototype(只有函數(shù)有,普通對象是沒有的),注意箭頭函數(shù)沒有prototype,構造函數(shù)也是函數(shù)所以也有prototype,這個屬性定義了構造函數(shù)制造出來的對象的公共祖先,通過該構造函數(shù)產生的對象可以繼承該原型的屬性和函數(shù),即person可以繼承Person.prototype上的函數(shù)
實例的原型都指向他的構造函數(shù)的原型對象,即person的原型指向Person.prototype
所有的函數(shù)(包括箭頭函數(shù),箭頭函數(shù)只是沒有prototype而已,也就是不能構造實例)的構造函數(shù)都是Function,即所有的函數(shù)都是Function的實例,包括Object,因為Object本身也是構造函數(shù),可以拿來構造對象,所以任何函數(shù)的原型都指向Function.prototype,所以Object的原型也指向Function.prototype,而Function是一個構造函數(shù),所以Function自己也是由Function.prototype構造的,即Function本身的原型也指向Function.prototype
普通對象是Object的實例,即由Object構造的所以Object是普通對象的構造函數(shù),所以普通對象的原型為Object,注意,構造函數(shù)是函數(shù),但是構造函數(shù)的prototype本身是一個非函數(shù)對象,即Person.prototype和Function.prototype的原型都指向Object.prototype
而Object.prototype理論上來說也是對象那也應該由Object.prototype構造,但是為了避免循環(huán)所以Object.prototype指向null
參考3,4可知原型鏈即對象的原型,原型的原型…,比如person的原型鏈為person=>Person.prototype=>Object.prototype=>null,并且要理解Person的原型鏈是Person=>Function.prototype=>Object.prototype=>null,Function的原型鏈是Function=>Function.prototype=>Object.prototype
注意,在構造函數(shù)中寫this.屬性那構造函數(shù)不會有這個屬性,因為這本質上是一條語句而不是屬性,this是指向調用方的,所以實例中會有這個屬性,比如
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,因為原型鏈從底往上找的一般像這種固定值的屬性沒必要放在Person中用this給實例定義,因為這樣一來每個實例都會創(chuàng)建一個,不如直接放在原型上即Person.prototype.name=15這樣如何Person里不再定義this.name
如果修改Person.prototype的引用即Person.prototype={}有兩種情況,若實例是在修改前定義的那實例將無法連接到新的Person.prototype上,因為他已經連接到舊的上了,如果在修改后定義那就連接在新的上面,注意Person能否連接到新的上面取決于新的引用是否將constructor指回Person,永遠記得Person.prototype也只是一個對象,他和Person的連接是通過上面的constructor對象屬性指向Person完成的,新對象如果直接沒定義constructor或者定義成別的那也連接不上Person
通過實例是無法修改構造函數(shù)原型上的屬性的,比如如果person.name='李四’那這個是給perosn實例這個對象上添加了一個叫name的屬性而不是Person.prototype.name被修改了; delete person.name只能刪除person自己的name屬性不會刪除Person.prototype的name屬性,但是注意即使person上沒name這個也會返回true,這不代表Person.prototype的name屬性被刪除了,而是執(zhí)行刪除沒找到要刪除的也算刪除成功 ;
到此這篇關于JavaScript原型鏈詳解的文章就介紹到這了,更多相關js原型鏈內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
在Postman的腳本中如何使用pm對象獲取接口的請求參數(shù)
這篇文章主要介紹了在Postman的腳本中如何使用pm對象獲取接口的請求參數(shù),本文通過實例代碼圖文相結合給大家介紹的非常詳細,需要的朋友可以參考下2023-09-09

