JavaScript中instanceof到底是以什么为依据呢?


可以查找到的资料都说"Javascript 的 instanceof 操作符可以用来比较两个操作数的构造函数 constructor"。例如: 细说JavaScript(三)
我在实际中却被搞糊涂了,请看如下代码:


 function O2(aa,bb){
    var aa = aa;
    this.bb = bb;
}
//1、正常情况
var o2 = new O2("a2","b2");
console.log(o2 instanceof O2);//true

//2、修改了构造函数的原型对象
var o4 = new O2("a4","b4");
O2.prototype = {};
console.log(o4 instanceof O2);//false

//3、修改了构造函数原型对象的constructor属性
var o6 = new O2("a6","b6");
O2.prototype.constructor = Object;
console.log(o6 instanceof O2);//true

问题来了:为什么2中可以导致false,而3中修改了构造函数原型对象的constructor属性却还是可以判断为true呢?说好的以constructor为依据呢?

新问题来了:
我在o4处已经改了O2.prototype = {};所以o4返回了false
为什么var o6 = new O2("a6","b6");之后,o6又成了true呢?
原型被o4处修改之后,原型对象不就永久改变了么?

javascript对象 JavaScript

Satilla 10 years, 7 months ago

http://yanhaijing.com/es5/#198
看这里ES5的实现

喜多村香菜❤ answered 10 years, 7 months ago

在实现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__ 中有这个属性,这就完成了属性/函数的重载

真汐波、恋萍 answered 10 years, 7 months ago

依据就是原型链 prototype !

o2 instanceof O2 意思是说 o2.__proto__ 能不能在 O2 的原型链上找得到.

第二个中本来 o2.__proto__ === O2.prototype , 但是你后面把 O2.prototype 改了, 所以就不等了, 结果自然是 false ;

第三个你只是改了 O2.prototype 中的一个属性, 没改变 O2.prototype 的指向, 所以返回 true ,

才不是萝莉控呢 answered 10 years, 7 months ago

Your Answer