11

instanceof「巨大な図書館」のフェアのパフォーマンスはどうですか?

これと同じように、プロトタイプチェーンを1つずつ上に移動しますか?:

//..
var _ = john.constructor;
while (true) {
    if (_ === Human) {
        return true;
    }
    _ = _.prototype.constructor
}
return false;
//..

instanceofすべてのオブジェクトのプロパティに一意のインターフェイスID番号を格納する場合と比較して、比較的パフォーマンスが低くなります。

4

3 に答える 3

12

ええ、そのようなもの。仕様の関連部分は次のとおりです。

11.8.6 instanceof 演算子

製品RelationalExpression : ShiftExpressionのRelationalExpression インスタンス は、次のように評価されます。

  1. lrefをRelationalExpressionの評価結果とします
  2. lvalを GetValue( lref )とします。
  3. ShiftExpressionを評価した結果を rref とます
  4. rvalを GetValue( rref )とします。
  5. Type( rval ) が Object でない場合、 TypeError例外をスローします。
  6. rvalに [[HasInstance]] 内部メソッドがない場合は、TypeError 例外をスローします
  7. [[HasInstance]] rval の内部メソッドを引数lvalで呼び出した結果を返します。

[[HasInstance]] メソッドの呼び出しは次のように定義されます。

15.3.5.3 [[HasInstance]] (V)

Fが Function オブジェクトであると仮定します。

Fの [[HasInstance]] 内部メソッドが値Vで呼び出されると、次の手順が実行されます。

  1. Vがオブジェクトでない場合は、 falseを返します。
  2. Fの [[Get]] 内部メソッドをプロパティ名 "prototype" で呼び出した結果をOする
  3. Type( O ) が Object でない場合、TypeError例外をスローします。
  4. 繰り返し
    ます。VをVの [[Prototype]] 内部プロパティの値とします
    b. Vnullの場合、 falseを返します。
    c. OVが同じオブジェクトを参照している場合は、 true を返します

パフォーマンスについて: これはおそらくブラウザの実際の実装に依存します。それらの間には大きな違いがある可能性があるため、http://jsperf.com/などでいくつかのベンチマークを作成することをお勧めします。


の問題instanceofは、frame や iframe など、異なるコンテキストの要素で呼び出すと機能しない可能性があることです。たとえば、a経由でアクセスできるオブジェクトiframe.contentWindow.aであり、それが配列であるかどうかをテストしたい場合、

iframe.contentWindow.a instanceof Array

戻りfalseます。

于 2011-05-08T01:35:03.440 に答える
12

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ミリ秒のパフォーマンスの違いが見られない場合、パフォーマンスへの影響はないと想定しても安全だと思います:)

于 2011-05-08T01:36:38.597 に答える
7

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;
    }
}
于 2012-10-13T15:09:38.817 に答える