問題
Function.prototype.a = () => {
console.log(1);
}
Object.prototype.b = () => {
console.log(2);
}
function A() {}
const a = new A();
a.a();
a.b();
A.a()
筆者第一反應就懵逼,搞不懂特意放一個 Function.prototype.a
干什么,因為 function A
的原型鏈屬性 prototype 只和 Object
有關系,和 Function
對象本身沒啥關系。
面試中筆者猜測
a.a() // 會無法執行,因為 A 的原型的原型,我知道是 Object 而非 Function。
a.b() // 正常打印 2,因為 Object 的原型被加上了 b 方法,順着原型鏈能被找得到。
A.a() // 第一反應和 a.a() 沒有區別,因為順着原型鏈還是只能找到 Object。但是面試官特意放上來這個,就讓筆者疑神疑鬼的。
輸出結果
最后面試完,特意去輸出了下結果
a.a() // Uncaught TypeError: a.a is not a function
a.b() // 2
A.a() // 1
A.b() // 2
也就是說 A 可以找到 Function.prototype 和 Object.prototype 的屬性。而 a 只能找到 Object.prototype 的。
嗯,這個 A 挺讓人困惑的。
A instanceof Object // true
A instanceof Function // true
a instanceof A // true
a instanceof Object // true
a instanceof Function // false
分析
對於 new 出來的對象 a 的屬性,原型鏈查找的順序應該是
- a 自身
a.__proto__
相當於 A.prototypeA.prototype.__proto__
相當於 Object.prototypeObject.prototype.__proto__
這個為 null,原型鏈查找到頭。
對於 function 定義的函數 A 的屬性,原型鏈查找順序應該是
- A 自身
A.__proto__
相當於 Function.prototypeFunction.prototype.__proto__
等於 Object.prototypeObject.prototype.__proto__
這個為 null,原型鏈查找到頭。
總之幾點原則:
- 所有構造函數的的 prototype 方法的
__proto__
都指向 Object.prototype (除了 Object.prototype 自身) - Object 是 Function 的實例對象,
Object.__proto__ === Function.prototype // true
- Function.prototype 是 Object 的實例對象。
Function.prototype.__proto__ === Object.prototype // true
參考
這篇對 Object 和 Function 的關系講得很好,可以參考。