JavaScript中instanceof的判断依据
读jquery源码的时候,发现作者为了让创建jquery对象更容易使用了用函数返回对象的方法
jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context, rootjQuery ); }
jQuery 对象的方法都定义在jQuery.prototype 上,然后init也是原型上的一个方法,为了让jQuery.fn.init构造函数能够继承jQuery.prototype上的方法把jQuery.fn.init.prototype指向了jQuery.prototype
jQuery.fn = jQuery.prototype = { constructor: jQuery, ..., init: function( selector, context, rootjQuery ) {}, ..., }
jQuery.fn.init.prototype = jQuery.fn;
这样是妥善解决了方法继承问题,但是有个疑问:构造函数jQuery.fn.init创建的实例的对象类型是jQuery对象吗?
var obj = jQuery(); obj instanceof jQuery.fn.init //true obj instanceof jQuery //这里obj好像跟jQuery 毫无关系
但是试了一下jQuery 方法创建的对象确实是jQuery的实例也就是说obj instanceof jQuery 为true;
于是就引出了JavaScript中instanceof的判断依据是什么的困惑,百思不得其解,网上查了一下原来是根据实例的__proto__ 属性。
instanceof的判断依据:
在实现js的继承的时候,每一个用new 构造出来的对象都会有一个私有的属性,在firefox和chrome中这个私有的属性叫做 __proto__,在 IE中也有一个这样类的的私有属性,只不过没有暴露给用户。
这个属性指向其构造函数的 prototype ,在执行 o2 = new O2() 的时候会有类似这样的赋值o2.__proto__ = O2.prototype所以在chrome 和 firefox中:
o2 instaneof O2 其实相当于 o2.__proto__ === O2.prototype || o2.__proto__.__proto__ === O2.prototype || ...
IE中也是类似,只不过这个属性不叫 __proto__
P.S 继承的实现:
当你读取 o2.pro 的时候,会现在o2中寻找有没有一个叫 pro 的属性,没有的话就去o2.__proto__中找有没有,还没有的话,就去o2.__proto__.__proto__中去找(记住一个对象的__proto__就是其构造函数的prototype)。。。这样一直下去其实最终会找到 Object.prototype,这样就实现了所有的对象都继承了Object。
当你写入 o2.pro 的时候就只会在o2中查找,不会递归的查找o2.__proto__,这样就会得到一个新的(如果没有的话)pro属性,然后当你再次访问 o2.pro 的时候,就是访问的这个新的属性,即使o2.__proto__中有这个属性,这就完成了属性/函数的重载