Pac*_*ier 9 javascript inheritance instanceof
instanceof
"巨型图书馆" 的公平表现如何?
它是否一个接一个地沿原型链传播,类似于此?:
//..
var _ = john.constructor;
while (true) {
if (_ === Human) {
return true;
}
_ = _.prototype.constructor
}
return false;
//..
Run Code Online (Sandbox Code Playgroud)
instanceof
与在每个对象的属性中存储唯一的接口ID号相比,相对来说是不相容的.
Fel*_*ing 11
是的,那样的.以下是规范中的相关部分:
ShiftExpression的生产RelationalExpression:RelationalExpression 实例 的计算方法如下:
- 让lref成为评估RelationalExpression的结果.
- 设lval为GetValue(lref).
- 让rref成为评估ShiftExpression的结果.
- 设rval为GetValue(rref).
- 如果Type(rval)不是Object,则抛出TypeError异常.
- 如果rval没有[[HasInstance]]内部方法,则抛出TypeError异常.
- 返回使用参数lval调用rval的[[HasInstance]]内部方法的结果.
其中调用[[HasInstance]]方法被定义为
假设F是一个Function对象.
当使用值V调用F的[[HasInstance]]内部方法时,将执行以下步骤:
- 如果V不是对象,则返回false.
- 设O是使用属性名称" prototype " 调用F的[[Get]]内部方法的结果.
- 如果Type(O)不是Object,则抛出TypeError异常.
- 重复
一次.让V是[[原型]]内部的属性的值V.
湾 如果V为null,则返回false.
C.如果O和V引用同一个对象,则返回true.
关于性能:这可能取决于浏览器中的实际实现.它们之间可能存在巨大差异,因此最好的方法是制作一些基准测试,例如http://jsperf.com/.
一个问题instanceof
是,如果您在来自不同上下文的元素(例如框架或iframe)上调用它,它可能不起作用.例如,让a
你成为一个可以访问的对象iframe.contentWindow.a
,然后你想测试它是否是一个数组
iframe.contentWindow.a instanceof Array
Run Code Online (Sandbox Code Playgroud)
会回来的false
.
Mar*_*ahn 11
在V8(Chrome的JS引擎)中,似乎几乎没有任何性能影响:
> function A(){}
> function B(){}
> function C(){}
> function D(){}
> B.prototype = new A();
> C.prototype = new B();
> D.prototype = new C();
>
> var objA = new A();
> var objD = new D();
>
> var start = (+new Date()); for(var i=0; i<10000000; i++){ objA instanceof A } console.log((+new Date()) - start);
138
> var start = (+new Date()); for(var i=0; i<10000000; i++){ objD instanceof A } console.log((+new Date()) - start);
138
Run Code Online (Sandbox Code Playgroud)
Firefox显示相同的行为.
在这里有点疯狂,但是:
> var classes = [];
> for(var i=0; i<10000; i++){
> classes[i] = function(){};
> i && (classes[i].prototype = new (classes[i-1])());
> }
>
> var obj0 = new classes[0],
> obj9999 = new classes[9999];
>
> var start = (+new Date()); for(var i=0; i<10000000; i++){ obj0 instanceof classes[0] } console.log((+new Date()) - start);
138
> var start = (+new Date()); for(var i=0; i<10000000; i++){ obj999 instanceof classes[0] } console.log((+new Date()) - start);
138
Run Code Online (Sandbox Code Playgroud)
我认为可以安全地假设没有性能损失,如果它可以钻取10,000个类而不会看到1毫秒的性能差异:)
小智 7
根据Felix Kling所引用的,所有instanceof做的(不包括错误检查)是检查函数的原型属性(必须是对象)是否可以在原型链的某处找到
person instanceof Object
// ROUGHTLY does
return (
person.__proto__==Object.prototype
|| person.__proto__.__proto__==Object.prototype
|| ... );
Run Code Online (Sandbox Code Playgroud)
这是一些伪代码:
person instanceof Person
//ROUGHTLY equals
person.instanceOf(Person)
person.instanceOf = function(Person) {
if(typeof Person!='object') throw new TypeError;
if(!([[HasInstance]] in Person)) throw new TypeError;
return Person.[[HasInstance]](this /* person */)
}
Person.[[HasInstance]] = function(V) {
if(typeof V!='object') return false;
var O = this.prototype;
if(typeof O!='object') throw new TypeError;
while(true) {
V = V.__proto__; // [[prototype]] (hidden) property
if(V==null) return false;
if(V==O) return true;
}
}
Run Code Online (Sandbox Code Playgroud)