JS原型鏈、prototype、__proto__、原型鏈繼承詳解

Bill Cheng?發表於2019-02-26

prototype__proto__的區別:

Javascript中所有的物件都是Object的例項,並繼承Object.prototype的屬性和方法,也就是說,Object.prototype是所有物件的父級。

在物件建立時,就會有一些預定義的屬性,其中定義函式的時候,這個預定義屬性就是prototype,這個prototype是一個普通的物件。 而定義普通的物件的時候,就會生成一個__proto__,這個__proto__指向的是這個物件的建構函式的prototype.

function A () {}

let a = new A()
複製程式碼

當我們宣告一個函式A時就自動建立了prototype物件。而a是建構函式A的例項,這時候a是一個例項物件,因為例項物件只有__proto__屬性, 所以a只有__proto__屬性,此屬性指向A.prototype

所以:

// 每個例項物件(object)都有一個私有屬性(稱之為__proto__)指向它的原型物件(prototype)
a.__proto__ === A.prototype // true 
複製程式碼

這就是prototype__proto__的區別。

原型鏈

我們都知道物件都有一個toString方法。上述的例項化物件a也可以toString。而例項化物件a本身並沒有toString的方法,那他就會沿著它的__proto__向他的建構函式A的prototype物件去找,而這裡也沒有,那他就會繼續沿著A.prototype.__proto__向上找。而A.prototype.__proto__指向的就是Object.prototype。(這也同時也解釋了為什麼所有的javascript物件都具有Object的基本方法。)

a.toString() === Object.prototype.toString() // true
複製程式碼

這一層一層的連結關係就是原型鏈,層層向上直到一個物件的原型物件為 null(Object.prototype.__proto__ === null)。根據定義,null 沒有原型,並作為這個原型鏈中的最後一個環節。

用程式碼表示就是:

a.__proto__ === A.prototype // true 
A.prototype.__proto__ === Object.prototype // true

==>
a.__proto__.__proto__ === Object.prototype // true
複製程式碼

原型鏈繼承

有了上面的理論支援,再理解原型鏈繼承就十分簡單了

function Parent(){
    this.name = 'mike';
}

function Child(){
    this.age = 12;
}
Child.prototype = new Parent(); // Child繼承Parent,通過原型,形成鏈條
複製程式碼

這個時候Child.prototype已經是{ name: 'mike' }

let childA = new Child() // 建立例項

console.log(childA) // { age: 12 }
複製程式碼

childA中並沒有name屬性,但是根據我們在上面討論的,原型鏈會一層層向上找,所以:

childA.name === childA.__proto__.name === Child.prototype.name // true

console.log(childA.name) // mike
複製程式碼

參考連結:

1、繼承與原型鏈

2、徹底理解什麼是原型鏈,prototype和__proto__的區別。

相關文章