13 Stimmen

Warum ist der Operator "in" von Javascript konsequent langsamer als der strenge Vergleich mit undefined?

Siehe http://jsperf.com/in-vs-member-object-access

Im Wesentlichen warum ist das Überprüfen von if ('bar' in foo) {} signifikant langsamer als if (foo.bar !== undefined) {}?

5voto

Ibu Punkte 41144

foo.bar !== undefined überprüft nur diese 2 Werte, um festzustellen, ob sie übereinstimmen.

Während 'bar' in foo einen Mechanismus verwenden muss, um die Eigenschaften von foo zu durchlaufen und zu sehen, ob bar darin ist.

Hier ist eine interessante Lektüre von Ecma-Script

Der in-Operator

Die Produktion RelationalExpression: RelationalExpression in ShiftExpression wird wie folgt ausgewertet:
1. Bewertung von RelationalExpression.
2. Aufruf von GetValue(Result(1)).
3. Bewertung von ShiftExpression.
4. Aufruf von GetValue(Result(3)).
5. Wenn Result(4) kein Objekt ist, wird eine TypeError-Ausnahme ausgelöst.
6. Aufruf von ToString(Result(2)).
7. Aufruf der Methode [[HasProperty]] von Result(4) mit dem Parameter Result(6).
8. Rückgabe von Result(7).

Der strenge Ungleichheitsoperator ( !== )

============================================

Die Produktion EqualityExpression: EqualityExpression !== RelationalExpression wird wie folgt ausgewertet:
1. Bewertung von EqualityExpression.
2. Aufruf von GetValue(Result(1)).
3. Bewertung von RelationalExpression.
4. Aufruf von GetValue(Result(3)).
5. Durchführung des Vergleichs Result(4) === Result(2). (Siehe unten.)
6. Wenn Result(5) wahr ist, wird false zurückgegeben. Andernfalls wird true zurückgegeben.

4voto

Jason Orendorff Punkte 39655

Du hast recht. Es macht keinen Sinn, dass "bar" in foo langsamer ist als foo.bar.

Der einzige Grund, warum in nicht genauso schnell ist, ist, dass es nicht so viel Aufmerksamkeit von JIT-Ingenieuren erhalten hat wie die viel häufigere Syntax foo.bar.

Vor allem im Fall Ihres jsperf-Tests, wo die Eigenschaft als direkte Eigenschaft auf foo selbst vorhanden ist (nicht als Prototyp), liegt es nahe, dass 'bar' in foo nicht langsamer sein sollte als foo.bar !== undefined. Wenn überhaupt, sollte es schneller sein. Der Hauptunterschied zwischen den beiden ist, dass in beantwortet werden kann, ohne den Wert der Eigenschaft überhaupt zu überprüfen!

Im Fall von foo.bar erwarte ich, dass sowohl der V8-Motor als auch der SpiderMonkey-Motor erkennen werden, dass der Code nichts Nützliches tut (das heißt, er hat keine beobachtbaren Effekte) und ihn vollständig optimieren werden. Der Benchmark misst keine tatsächliche Arbeit.

Scheinbar sind die Motoren noch nicht klug genug, um "bar" in foo zu optimieren, aber es ist nur eine Frage der Zeit. Und der Prioritäten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X