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
複製程式碼