JS原形鏈

Swiftly發表於2019-01-13

圖一:

js prototype chain

圖二

JS原形鏈

先上兩張關於原型鏈的圖,可以從中發現四個部分instance(例項物件)自定義函式FunctionObject

從一層f1.__proto__ === Foo.prototype說起

function Foo() {}
let f1 = new Foo()
// f1.__proto__引用了Foo.prototype
console.log(f1.__proto__ === Foo.prototype) // true
複製程式碼

任何一個由new關鍵字生成的例項物件都會有一個__proto__引用函式的prototype。如上f1.__proto__ === Foo.prototype。那麼問題來了,例項物件的__proto__是如何引用函式的prototype物件的。

  1. 重寫new關鍵字

     function new(Func, arguments) {
         let o = {}
         if (Func && typeof Func === 'function') {
             o.__proto__ = Func.prototype
             Func.apply(o, arguments)
             return o
         }
     }
    複製程式碼

從重寫的new方法中,可以知道,o.__proto__ = Func.prototype,例項物件的__proto__引用函式的prototype。是由於關鍵字new方法實現的。

解開了第一層的面紗,來看看第二層面紗

函式對頂層函式的引用

從幾個問題談起

  1. Foo.__proto__ === Function.prototype // true
  2. Function.__proto__ === Function.prototype // true
  3. Object.__proto__ === Function.prototype // true

從圖一/二中都可以看出,任何一個函式自身也擁有一個__proto__,並引用頂層函式的prototype。可能這裡會有些奇怪,換一種思路,可以理解為任何函式都是頂層函式Function的物件,包括Function()和Object()函式

原形物件對原形物件的引用

  1. f1.__proto__ === Foo.prototype
  2. Foo.prototype.__proto__ === Object.prototype
  3. Function.prototype.__proto__ === Object.prototype
  4. Object.prototype.__proto__ null

沿著物件的原形,會逐級的往上,一直找到Object.prototype.__proto__ = null停止,物件原形的鏈的查詢遵循f1.__proto__.__proto__....,這樣構成了JS的原形鏈。

JS原形鏈
這裡需要注意的Object.prototype中定義了過個預設的方法,並且是不能修改的。

JS原形鏈

hasOwnProperty的使用

該方法不會去檢查物件的原形上是否存在指定的屬性,只會檢驗本身函式本身是否擁有這個屬性。

instanceof操作符的使用

a instanceof A
複製程式碼

方法判斷的是物件是否是一個函式的例項,這裡的入參a必須是是一個例項物件,A是一個函式。該操作符會檢查a是否在A的原形鏈中,所以會出現一下情況

Function instanceof Function // true
Object instanceof Fucntion // true
Obejct instanceof Object // true
Function instanceof Object // true
複製程式碼

相關文章