原型與原型鏈一知半解
前言
看過不少深入瞭解原型原型鏈系列,大體是明白不少,還是不夠透徹!以下僅為個人總結和理解。
初見各名詞
首先得了解這幾個詞:
函式,建構函式,函式原型(例項原型),例項,例項物件,物件原型,原型,prototype,proto,constructor
先看下面這個例子:
function Person() {
}
function Foo() {
}
const foo = new Foo();
const person = new Person();
函式,建構函式:在上面的例子中建構函式就是Person
函式原型(例項原型):後面會結合式子闡述。(我的理解是最初始的函式,他的屬性所有函式使用)
例項與例項物件:在上面的例子中,有建構函式Person、Foo,我們用new操作符例項化了foo例項物件、person例項物件
原型物件與原型:後面會結合式子闡述。
原型
任何一個建構函式都會有prototype屬性。列印建構函式Foo.prototype,Person.prototype你會發現
console.log(Foo.prototype,Person.prototype);
//{ constructor: f Foo(), __proto__: Object } { constructor: f Person(), __proto__: Object }
Foo.prototype,Person.prototype它們都指向各自函式的原型物件
a) 任何一個建構函式函式(Person,Foo),都擁有一個prototype屬性,它指向這個函式的原型物件
從打印出來的式子
{
constructor: f Foo(),
__proto__: Object
}
{
constructor:
constructor: f Person(),
__proto__: Object
}
不難看出 Person.prototype和Foo.prototype都有constructor和__proto__屬性。
而且Person.prototype.constructor和Foo.prototype.constructor都指向的是各自的建構函式本身。
可以通過式子大膽驗證下:
console.log(Person.prototype.constructor === Person) // true
console.log(Foo.prototype.constructor === Foo) // true
b) 建構函式的prototype的constructor都是指向的建構函式的本身
那麼Person.prototype.__proto__和Foo.prototype.__proto__指向什麼呢?
console.log(Person.prototype.__proto__ === Object.prototype) // true
console.log(Foo.prototype.__proto__ === Object.prototype) // true
上式中的Person.prototype.__proto__和Foo.prototype.__proto__都指向Object.prototype
c) Person.prototype的原型指向Object.prototype
也就是說每個函式的原型都是Object的例項,那麼Object.prototype的原型,new出來的foo,person的原型呢?
console.log(foo.__proto__);//{ constructor: f Foo(), __proto__: Object }
console.log(person.__proto__);//{ constructor: f Person(), __proto__: Object }
console.log(Object.prototype.__proto__);//null
不難看出
console.log(foo.__proto__===Foo.prototype);//true
console.log(person.__proto__===Person.prototype);//true
console.log(Object.prototype.__proto__===null);//true
d) foo,person的__proto(例項的原型) === Person.prototype;因此把Person.prototype叫做例項原型。
e) Person.prototype.proto(例項原型的原型) === Object.prototype;因此例項原型的原型指向的是Object.prototype。
f) Object.prototype.proto(Object.prototype的原型) === null;因此Object.prototype.proto 的值為null,也就是Object.prototype沒有原型。
再上面的 b 項中式子拿下來(b.建構函式的prototype的constructor都是指向的建構函式的本身)
console.log(Person.prototype.constructor === Person) // true
console.log(Foo.prototype.constructor === Foo) // true
那麼Object.prototype.constructor是不是也是Object本身呢?
console.log(Object.prototype.constructor===Object)//true
g) Object.prototype.constructor === Object
由此訝羽大佬的關係圖也就清晰了
原型鏈
由上面的分析,可以看出原型鏈實際上就是執行const foo = new Foo()語句(建立例項函式時),產生了一個鏈條反應,這個最頂端也就是原型鏈最頂端是Object.prototype.__proto__為null。
總結:從一個例項物件往上查詢構造這個例項的相關聯物件(原型物件),這個關聯的物件(原型物件)通過__prototo__屬性再往上找創造他的原型物件,以此類推,一直往上找,直到Object.prototype的原型物件為null結束的過程。
原型鏈是通過prototype的原型和__proto__的屬性來完成原型鏈的查詢。