1. 以下這張圖,基本解釋了所有的原型關係
核心要素是:
var Foo = function (){}
var foo = new Foo()
foo.__proto__ == foo.constructor.prototype == Foo.prototype
// .__proto__ 其實是 .construstor.prototype 的簡寫
其實應該不是簡寫,當我把對象的constructor
置爲null
,.__proto__
還是能夠讀到,但是.constructor.prototype
直接報錯了。這裏這麼說只是爲了方便理解
說到底.__proto__
就是這個對象的構造函數的原型。
理解了這個就能理解上面圖示的所有的關係了。
2. 以下點有助於理解幾個基類之間的關係
instanceof 操作符
instanceof的左值一般是一個對象,右值一般是一個構造函數,用來判斷左值是否是右值的實例。它的內部實現原理是這樣的:
//設 L instanceof R
//通過判斷
L.__proto__.__proto__ ..... === R.prototype ?
//最終返回true or false
也就是沿着L的__proto__
一直尋找到原型鏈末端,直到等於R.prototype
爲止。知道了這個也就知道爲什麼以下這些奇怪的表達式爲什麼會得到相應的值了
Function instanceof Object // true
Object instanceof Function // true
Function instanceof Function //true
Object instanceof Object // true
Number instanceof Number //false
3. 總結了下
Object.constructor == function Function (){}
Function.constructor == function Function (){}
兩個需要特殊注意一下, 記住這個基本上能把所有的東西都推理出來了。
1.Function.prototype 結果爲 functoin (){ // native code }
2.Function.prototype.constructor 結果爲 Funtion 本身
3.Function.prototype.constructor.prototype 結果爲 function (){// native code }
...無線循環
4.Function.prototype.__proto__ 結果爲 Object.prototype
5.Object.prototype.__proto__ 爲 null
4. 關於 proto
__proto__
是內部的構造函數原型對象
, 一般情況下
obj.__proto__ === obj.constructor.prototype // true
但是__proto__
不會因爲你在對象的prototype中更改constructor而改變。它總是指向對象被創建時的那個constructor
function , 舉個例子:
// 在學習原型鏈的時候是這樣繼承的
function Animal(){}
function Dog(){}
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog; // 在繼承的時候,這裏改變了prototype.constructor,但是不影響__proto__的結果
// 完成繼承
new Dog() instanceof Animal // true
new Dog() instanceof Dog // true
// 根據以上 instanceof 的原理
new Dog().__proto__.__proto__ === Animal.prototype // true
// 在這裏__proto__和constructor.prototype是不一樣的,
new Dog().__proto__.constructor.prototype === Animal.prototype // false
部分內容摘自
作者:蘇墨橘
鏈接:https://www.zhihu.com/question/34183746/answer/59043879