以下这张图,基本解释了所有的原型关系
核心要素是:
1 2 3 4 5 var Foo = function ( ) {}var foo = new Foo()foo.__proto__ == foo.constructor.prototype == Foo.prototype
但本质上__proto__
不等于.constructor.prototype
,当我把对象的constructor
置为null
,.__proto__
还是能够读到,但是.constructor.prototype
直接报错了。这里这么说只是为了方便理解 说到底.__proto__
就是这个对象的构造函数的原型。
理解了这个就能理解上面图示的所有的关系了。
以下有助于理解几个基类之间的关系 instanceof
操作符
instanceof的左值一般是一个对象,右值一般是一个构造函数,用来判断左值是否是右值的实例。它的内部实现原理是这样的:
1 2 3 4 //设 L instanceof R //通过判断 L.__proto__.__proto__ ..... === R.prototype ? //最终返回true or false
也就是沿着L的__proto__
一直寻找到原型链末端,直到等于R.prototype
为止。知道了这个也就知道为什么以下这些奇怪的表达式为什么会得到相应的值了
1 2 3 4 5 Function instanceof Object // true Object instanceof Function // true Function instanceof Function //true Object instanceof Object // true Number instanceof Number //false
总结了下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Object .constructor === function Function ( ) {} Function .constructor === function Function ( ) {} Function .prototype === functoin (){ native code } Function .prototype.constructor === Funtion Function .prototype.constructor.prototype === function ( ) { native code } Function .prototype.__proto__ === Object .prototype Object .prototype.__proto__ === null
关于__proto__
__proto__
是内部的构造函数原型对象 , 一般情况下
1 obj.__proto__ === obj.constructor.prototype
但是__proto__
不会因为你在对象的prototype中更改constructor而改变。它总是指向对象被创建时的那个constructor
function , 举个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function Animal ( ) {}function Dog ( ) {}Dog.prototype = new Animal(); Dog.prototype.constructor = Dog; new Dog() instanceof Animal new Dog() instanceof Dog new Dog().__proto__.__proto__ === Animal.prototype new Dog().__proto__.constructor.prototype === Animal.prototype new Dog().__proto__.constructor.prototype === Dog.prototype
部分内容摘自 作者:苏墨橘 链接:https://www.zhihu.com/question/34183746/answer/59043879