Ich fragte diese Frage , und es stellte sich heraus Wenn beim Entfernen eines Attributs aus einem Element überprüft wird, ob das Element zuerst mit elem.xxx!==undefined
existiert, wird die Laufzeit schneller. Proof .
Warum ist es schneller? Es gibt mehr Code, den du durchgehen und du musst der Methode removeAttribute()
auf jeden Fall begegnen gehe darüber.
Nun, zuerst müssen Sie wissen, dass elem.xxx
nicht dasselbe ist wie elem.getAttribute()
oder eine andere Methode relativ zum Attribut.
elem.xxx
ist eine Eigenschaft eines DOM-Elements, während das Attribut und das Element im HTML-Code innerhalb des DOM ähnlich, aber unterschiedlich sind. Nehmen wir als Beispiel dieses DOM-Element: <a href="#">
und diesen Code:
Aber nehmen wir ein benutzerdefiniertes Attribut: <a custom="test">
Sie können also die Geschwindigkeit von beiden nicht wirklich vergleichen, da sie nicht das gleiche Ergebnis erzielen. Aber eines ist deutlich schneller, da Eigenschaften ein Schnellzugriffsdaten sind, während Attribute die get / hasAttribute DOM-Funktionen verwenden.
Nun, warum ohne die Bedingung ist schneller? Nur weil removeAttribute
nicht interessiert, ist das Attribut fehlt, überprüfen Sie, ob es nicht ist.
Die Verwendung von hasAttribute
vor removeAttribute
ist also wie die doppelte Überprüfung, aber die Bedingung ist etwas langsamer, da überprüft werden muss, ob die Bedingung zum Ausführen des Codes erfüllt ist.
Ich habe den Verdacht, dass der Grund für die Geschwindigkeitssteigerung Trace-Bäume sind.
Trace Bäume wurden zuerst von Andreas Gal und Michael Franz von der Universität von Kalifornien, Irvine, in ihrer Arbeit Inkrementelle dynamische Codegenerierung mit Ablaufverfolgungsbäumen .
In seinem Blogbeitrag Tracing the Web Andreas Gal (der Co-Autor des Artikels) erklärt, wie das Verfolgen von Just-in-Time-Compilern funktioniert.
Um das Verfolgen von JIT-Compilern so sententiell wie möglich zu erklären (da mein Wissen über das Thema nicht tiefgehend ist), macht ein Tracing-JIT-Compiler Folgendes:
true
Zweig einer if
Anweisung ausgeführt wird). Sehen wir uns nun Ihren Code an und verstehen Sie, was den Geschwindigkeitsschub verursacht:
Dieser Code hat einen Code-Pfad (d. h. eine if
-Anweisung). Denken Sie daran, dass Tracing-JITs nur Codepfade und nicht ganze Funktionen optimieren. Dies ist, was ich glaube, geschieht:
hasAttribute
, der nicht JIT-kompiliert wird, da es nicht Teil des bedingten Codepfads ist (der Code zwischen den geschweiften Klammern). In diesem Testfall haben wir keine bedingten Codepfade. Daher tritt der JIT-Compiler niemals ein. Der Code ist also langsam.
Dies ist das gleiche wie im ersten Testfall mit einem signifikanten Unterschied:
elem.xxx
oder undefined
nicht bei jeder Iteration ändert, macht diese Optimierung die bedingte Prüfung noch schneller. Natürlich sind das nur Spekulationen von meiner Seite. Ich kenne die Interna einer JavaScript-Engine nicht und meine Antwort ist daher nicht kanonisch. Ich bin jedoch der Meinung, dass es sich um eine gute Vermutung handelt.
Wie Karl-André Gagnon darauf hingewiesen hat, sind der Zugriff auf eine [native] JavaScript-Eigenschaft und das Aufrufen einer DOM-Funktion / -Eigenschaft zwei verschiedene -Operationen .
Einige DOM-Eigenschaften werden als JavaScript-Eigenschaften über die DOM IDL ; Diese sind nicht gleich wie adhoc JS-Eigenschaften und erfordern DOM-Zugriff. Auch wenn die DOM-Eigenschaften offengelegt werden, gibt es keine strikte Beziehung mit DOM-Attributen !
Zum Beispiel aktualisiert inputElm.value = "x"
nicht das DOM-Attribut , obwohl das Element einen aktualisierten Wert anzeigt und meldet. Wenn das Ziel mit DOM-Attributen umgehen soll, ist die einzige korrekte Methode die Verwendung von hasAttribute/setAttribute
, etc.
Ich habe daran gearbeitet, einen "fairen" Mikro-Benchmark für die verschiedenen Funktionsaufrufe abzuleiten, aber es ist ziemlich schwierig und es gibt viele von verschiedenen Optimierungen, die auftreten. Hier mein bestes Ergebnis , mit dem ich meinen Fall argumentieren werde.
Beachten Sie, dass no if
oder removeAttribute
vorliegt, um die Ergebnisse zu verwirren, und ich fokussiere nur auf den DOM / JS-Eigenschaftenzugriff. Außerdem versuche ich, die Behauptung auszuschließen, dass die Geschwindigkeitsdifferenz nur auf einen Funktionsaufruf zurückzuführen ist, und ich ordne die Ergebnisse zu, um eklatante Browseroptimierungen zu vermeiden. YMMV.
Beobachtungen:
Der Zugriff auf eine JS-Eigenschaft ist fast . Dies ist zu erwarten 1,2
Das Aufrufen einer Funktion kann höhere Kosten verursachen als der Zugriff auf direkte Eigenschaften 1 , ist aber bei weitem nicht so langsam wie DOM-Eigenschaften oder DOM-Funktionen . Das heißt, es ist nicht nur ein "Funktionsaufruf", der hasAttribute
so viel langsamer macht.
Der Zugriff auf DOM-Eigenschaften ist langsamer als der Zugriff auf native JS-Eigenschaft ; Die Leistung unterscheidet sich jedoch stark zwischen den DOM-Eigenschaften und den Browsern. Mein aktualisierter Micro-Benchmark zeigt einen Trend, dass der DOM-Zugriff - sei es via DOM-Eigenschaft oder DOM-Funktion - möglicherweise langsamer ist als der native JS-Eigenschaftenzugriff 2 .
Und zurück zum Anfang: Der Zugriff auf eine Nicht-DOM [JS] -Eigenschaft für ein Element ist grundlegend anders als der Zugriff auf eine DOM-Eigenschaft weniger ein DOM-Attribut , auf demselben Element. Es ist dieser grundlegende Unterschied, und Optimierungen (oder das Fehlen davon) zwischen den Ansätzen zwischen den Browsern, die für die beobachteten Leistungsunterschiede verantwortlich sind.
1 IE 10 macht einen cleveren Trick, bei dem der gefälschte Funktionsaufruf sehr schnell ist (und ich vermute, dass der Aufruf gelöscht wurde), obwohl er einen abgründigen JS-Eigenschaftenzugriff hat. Betrachtet IE jedoch einen Ausreißer oder lediglich eine Verstärkung, dass der Funktionsaufruf nicht ist, was das von Natur aus langsamere Verhalten einführt, so beeinträchtigt dies nicht mein Hauptargument: Es ist der Zugriff auf DOM das ist grundsätzlich langsamer.
2 Ich würde gerne sagen, DOM-Eigenschaft Zugriff ist langsamer, aber FireFox macht einige erstaunliche Optimierung von input.value
(aber nicht img.src
). Es gibt eine besondere Magie, die hier passiert. Firefox optimiert das DOM-Attribut nicht.
Und verschiedene Browser können ganz andere Ergebnisse zeigen. Ich denke jedoch nicht, dass man irgendeinen "Zauber" mit dem if
oder removeAttribute
in Betracht ziehen muss, um zumindest das zu isolieren, was ich glaube. Leistungsproblem ": tatsächlich das DOM verwenden .
Tags und Links javascript dom performance syntax conditional