instanceof
“大图书馆”的公平表现如何?
它是否像这样一一地沿着原型链向上移动?:
//..
var _ = john.constructor;
while (true) {
if (_ === Human) {
return true;
}
_ = _.prototype.constructor
}
return false;
//..
与在instanceof
每个对象的属性中存储唯一的接口 id 号相比,它的性能相对较差。
instanceof
“大图书馆”的公平表现如何?
它是否像这样一一地沿着原型链向上移动?:
//..
var _ = john.constructor;
while (true) {
if (_ === Human) {
return true;
}
_ = _.prototype.constructor
}
return false;
//..
与在instanceof
每个对象的属性中存储唯一的接口 id 号相比,它的性能相对较差。
是的,类似的东西。这是规范中的相关部分:
产生式RelationalExpression : RelationalExpression instanceof ShiftExpression的评估如下:
- 令lref为评估RelationalExpression的结果。
- 令lval为 GetValue( lref )。
- 令rref为评估ShiftExpression的结果。
- 设rval为 GetValue( rref )。
- 如果 Type( rval ) 不是 Object,则抛出TypeError异常。
- 如果rval没有 [[HasInstance]] 内部方法,则抛出TypeError异常。
- 返回使用参数lval调用rval的 [[HasInstance]] 内部方法的结果。
其中调用 [[HasInstance]] 方法定义为
假设F是一个 Function 对象。
当F的 [[HasInstance]] 内部方法以值V被调用时,将采取以下步骤:
- 如果V不是对象,则返回false。
- 令O为使用属性名称“原型”调用F的 [[Get]] 内部方法的结果。
- 如果 Type( O ) 不是 Object,则抛出TypeError异常。
- 重复
一个。令V为V的 [[Prototype]] 内部属性的值。
湾。如果V为null,则返回false。
C。如果O和V引用同一个对象,则返回true。
关于性能:这可能取决于浏览器中的实际实现。它们之间可能存在巨大差异,因此最好的方法是进行一些基准测试,例如使用http://jsperf.com/。
一个问题instanceof
是,如果您在来自不同上下文的元素(例如框架或 iframe)上调用它,它可能无法正常工作。例如,让a
您可以访问的对象,iframe.contentWindow.a
并且您想测试它是否是一个数组,然后
iframe.contentWindow.a instanceof Array
将返回false
。
在 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
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
我认为如果它可以钻取 10,000 个类并且看不到 1 毫秒的性能差异,则可以安全地假设没有性能损失:)
根据 Felix Kling 引用的内容,instanceof 所做的一切(不包括错误检查)是检查是否可以在原型链的某个位置找到 Function 的原型属性(必须是对象)
person instanceof Object
// ROUGHTLY does
return (
person.__proto__==Object.prototype
|| person.__proto__.__proto__==Object.prototype
|| ... );
这是一些伪代码:
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;
}
}