圖一: app
圖二 函數
先上兩張關於原型鏈的圖,能夠從中發現四個部分instance(實例對象),自定義函數,Function,Object。spa
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
對象的。prototype
重寫new
關鍵字3d
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
方法實現的。code
解開了第一層的面紗,來看看第二層面紗cdn
從幾個問題談起對象
Foo.__proto__ === Function.prototype // true
Function.__proto__ === Function.prototype // true
Object.__proto__ === Function.prototype // true
從圖一/二中均可以看出,任何一個函數自身也擁有一個__proto__
,並引用頂層函數的prototype
。可能這裏會有些奇怪,換一種思路,能夠理解爲任何函數都是頂層函數Function
的對象,包括Function()和Object()函數
blog
f1.__proto__ === Foo.prototype
Foo.prototype.__proto__ === Object.prototype
Function.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ null
沿着對象的原形,會逐級的往上,一直找到Object.prototype.__proto__ = null
中止,對象原形的鏈的查找遵循f1.__proto__.__proto__....
,這樣構成了JS的原形鏈。原型鏈
該方法不會去檢查對象的原形上是否存在指定的屬性,只會檢驗自己函數自己是否擁有這個屬性。
a instanceof A
複製代碼
方法判斷的是對象是不是一個函數的實例,這裏的入參a必須是是一個實例對象,A是一個函數。該操做符會檢查a是否在A的原形鏈中,因此會出現一下狀況
Function instanceof Function // true
Object instanceof Fucntion // true
Obejct instanceof Object // true
Function instanceof Object // true
複製代碼