圖一:
圖二
先上兩張關於原型鏈的圖,可以從中發現四個部分instance(例項物件),自定義函式,Function,Object。
從一層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
物件的。
-
重寫
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
方法實現的。
解開了第一層的面紗,來看看第二層面紗
函式對頂層函式的引用
從幾個問題談起
Foo.__proto__ === Function.prototype // true
Function.__proto__ === Function.prototype // true
Object.__proto__ === Function.prototype // true
從圖一/二中都可以看出,任何一個函式自身也擁有一個__proto__
,並引用頂層函式的prototype
。可能這裡會有些奇怪,換一種思路,可以理解為任何函式都是頂層函式Function
的物件,包括Function()和Object()函式
原形物件對原形物件的引用
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的原形鏈。
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
複製程式碼