1. 程式人生 > 實用技巧 >原型與原型鏈一知半解

原型與原型鏈一知半解

前言

看過不少深入瞭解原型原型鏈系列,大體是明白不少,還是不夠透徹!以下僅為個人總結和理解。

初見各名詞

首先得了解這幾個詞:
函式,建構函式,函式原型(例項原型),例項,例項物件,物件原型,原型,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__的屬性來完成原型鏈的查詢。

原型與原型鏈一知半解