Funktionsaufrufe sind vernachlässigbar oder sogar optimieren in vorkompilierten Sprachen, die JS noch nie war. Darüber hinaus hängt viel vom Browser ab.
Sie sind der Tod aller Leistung in interpretierten Sprachen, die JS in erster Linie bis vor kurzem war. Die meisten modernen Browser haben JIT (Just In Time) -Compiler, was ein großes Upgrade von den JS-Interpretern der Vergangenheit ist, aber ich glaube, dass Funktionsaufrufe zu einem anderen Bereich noch einige Kosten verursachen, da das Aufrufobjekt von JS bestimmen muss, was tatsächlich aufgerufen wird verschiedene Scope-Ketten auf- und abmarschieren.
Also als eine allgemeine Regel: Wenn Sie über IE8 und niedrigere und ältere Versionen von Chrome und Firefox kümmern vermeiden Sie Funktionsaufrufe Zeitraum. Vor allem innerhalb von Schleifen. Für die JIT-Browser würde ich erwarten, dass eine Funktion, die in der anderen Funktion definiert ist, allgemein von Vorteil wäre (aber ich würde immer noch testen, da dies eine brandneue Technologie für IE9 ist und relativ neu für alle anderen).
Eine andere Sache, vor der man sich hüten sollte. Wenn eine Funktion besonders komplex ist, können JITs nichts tun, um sie zu optimieren.
https://groups.google.com/forum/#!msg/closure-compiler-discuss/4B4IcUJ4SUA/OqYWpSklTE4J
Aber das Wichtigste ist, zu verstehen, dass, wenn etwas gesperrt ist und nur in einem Kontext, wie eine Funktion innerhalb einer Funktion aufgerufen, soll es einfach sein für eine JIT zu optimieren. Außerhalb einer Funktion definiert, muss festgelegt werden, welche Definition dieser Funktion genau aufgerufen wird. Es könnte in einer äußeren Funktion sein. Es könnte global sein. Es könnte eine Eigenschaft des Prototyps des Konstruktors des Fensterobjekts sein, usw. In einer Sprache, in der Funktionen erste Klasse sind, dh ihre Referenzen als Argumente weitergegeben werden können, genauso wie Sie Daten weitergeben, können Sie diesen Schritt nicht wirklich vermeiden außerhalb Ihres aktuellen Kontextes.
Versuchen Sie also, Hypo in X zu definieren, um zu sehen, was passiert.
Noch ein paar allgemeine Tipps aus dem interpretierten Alter, die noch in JITs wertvoll sein könnte: ‚‘
Die Operator wie in someObject.property
, ist ein Prozess Caching wert. Es kostet Overhead, da es bei jeder Verwendung einen zugehörigen Aufrufobjekt-Lookup-Prozess gibt. Ich stelle mir vor, Chrome würde die Ergebnisse dieses Prozesses nicht beibehalten, da Änderungen an übergeordneten Objekten oder Prototypen das, was es tatsächlich referenziert, außerhalb eines bestimmten Kontextes verändern könnten. Wenn in Ihrem Beispiel x von einer Schleife verwendet wird (wahrscheinlich in Ordnung oder sogar hilfreich, wenn x in der gleichen Funktion wie die Schleife in JITs definiert ist - Mord in einem Interpreter), würde ich versuchen, Math.sqrt einer Variablen zuzuordnen, bevor Sie sie verwenden in Hypo. Zu viele Verweise auf Dinge außerhalb des Kontextes Ihrer aktuellen Funktion könnten dazu führen, dass einige JITs entscheiden, dass es sich nicht lohnt, zu optimieren, aber das ist reine Spekulation meinerseits.
Das folgende ist wahrscheinlich der schnellste Weg, um Schleife ein Array:
//assume a giant array called someArray
var i = someArray.length; //note the property lookup process being cached here
//'someArray.reverse()' if original order isimportant
while(i--){
//now do stuff with someArray[i];
}
Hinweis: Codeblock hier nicht aus irgendeinem Grund zu arbeiten.
Dies zu tun kann hilfreich sein, da es im Grunde den Inc/Dekrement-Schritt und den logischen Vergleich in nur das Dekrement verwandelt, wodurch die Notwendigkeit eines Links/Rechts-Vergleichsoperators vollständig entfällt. Beachten Sie, dass in JS der Dekrementoperator auf der rechten Seite bedeutet, dass ich zur Bewertung weitergeleitet und dann dekrementiert werde, bevor er innerhalb des Blocks verwendet wird. while(0)
wird zu false ausgewertet.
Ist Ihre Funktion außerhalb des Bereichs definiert, der millionenmal pro Sekunde ausgeführt wird? – alex
Und es ist nicht wahr, dass der Browser "weniger Kompilierung zu tun" hat, weil Sie es in eine Funktion einfügen ... es sollte in etwa gleich sein, besonders, da Kompilierung eine Startup-Sache ist. Aber @alex hat wahrscheinlich den Grund für Ihre 400% ige Verlangsamung :) – Ryan
@alex Ja, es ist im Hauptfenster definiert. – mindoftea