Javascript: variable Zuweisung in Funktionen

8

Betrachten Sie diese zwei Blöcke:

Block A

%Vor%

Block B

%Vor%

Ist ein Weg richtiger / effizienter als der andere? Natürlich ist dies ein verdichtetes Beispiel - in meinem Code gibt es mehr Variablen, und was ich versuche, ist Zeit zu sparen, indem man nicht jedesmal this.varName in die Funktionen eingibt, indem man die Variablen für den aktuellen Funktionsumfang neu zuweist. Es funktioniert, aber ist es richtig?

BEARBEITEN: Nur um zu verdeutlichen, werden die Variablen ausgiebig in den Funktionen verwendet. Allgemeiner Konsens scheint zu sein, dass hierfür eine Neuzuweisung durch lokalen Geltungsbereich der richtige Weg ist.

    
Alex 15.08.2011, 17:54
quelle

12 Antworten

7

Hängt davon ab. Wenn Sie den Wert nur einmal verwenden, ist es nicht sinnvoll, den Aufwand für das Speichern und anschließende Abrufen des Werts hinzuzufügen. Wenn Sie andererseits den Wert im Rahmen der Funktion mehrmals referenzieren, ist es sinnvoll, ihn nur einmal zu holen.

    
Jeremy Holovacs 15.08.2011 17:58
quelle
4

In

%Vor%

Die globale Zuweisung und Suche ist nicht nur weniger effizient, Sie belasten auch den globalen Gültigkeitsbereich, weil a = this.a der globalen a zuordnet.

BEARBEITEN:

Nehmen wir an, dass this.a und this.b einen Fänger auslösen und alert(a) einen Aufruf der Methode toString des Wertes von a verursachen.

Es gibt eine Reihenfolge der Betriebsunterschiede zwischen

%Vor%

was tut (get a, get b, a toString, b toString) und

%Vor%

was tut (get a, a toString, get b, b toString) und

Es kann einen guten Grund geben, eine Reihenfolge der Operationen der anderen vorzuziehen, aber Effizienz-weise ist die zweite wahrscheinlich besser.

Wegen des Unterschieds in der Reihenfolge der Operationen sollten Sie sich nicht auf einen Semantik erhaltenden JavaScript-Minifier verlassen, um die erste bis zur zweiten zu optimieren, wenn nur eine einzige Verwendung des Members besteht.

    
Mike Samuel 15.08.2011 17:58
quelle
3

Es kommt darauf an. Wenn Sie in Ihrer Funktion nur einmal auf die Eigenschaft zugreifen, ist die erste schneller. Wenn Sie mehrmals darauf zugreifen, ist es schneller, die modifizierte Version als zweiten Codeabschnitt zu verwenden.

Wenn Sie die zweite Version so ändern, dass a , b und c als lokale vars von f() deklariert werden, werden mehrere Scans der Scope-Kette und das Traversieren von this vermieden. Dies ist wiederum erforderlich um auf diese Eigenschaften mehrfach zuzugreifen.

    
JAAulde 15.08.2011 17:59
quelle
3

Nicholas Zakas nennt dies eine Möglichkeit, um JavaScript zu beschleunigen. Aus der Zusammenfassung des Videos:

  

Ähnlich wie bei globalen Variablen kann die Leistung verbessert werden, indem lokale Variablen erstellt werden, die Objekteigenschaften und Arrayelemente enthalten, auf die mehrfach verwiesen wird. Bedenken Sie außerdem, dass die Suche nach tieferen Objekteigenschaften und Arrayelementen (z. B. obj.name1.name2.name3) langsamer ist.

    
sdleihssirhc 15.08.2011 18:02
quelle
1

Der erste Weg, wenn relativ effizient, da auf die zweite Weise, Sie eine Kopie der Variablen machen, und damit eine zusätzliche Anweisung für alle Variablen und mehr Speicherplatz belegt wird (sowohl durch den Code und die Variablen ).

    
Pheonix 15.08.2011 17:57
quelle
1

Sie vermissen einige wichtige Dinge in Ihren Beispielen. Ich werde mich nur auf die Funktion f konzentrieren, nehme an, dass der Rest des Codes derselbe ist:

Wenn Sie einfach auf Werte zugreifen, die auf dem Objekt gespeichert sind, gibt es keinen Grund, eine temporäre Variable zu speichern, es wird nur die Arbeit zunichte machen:

%Vor%

Wenn Sie jedoch Berechnungen durchführen und die Ergebnisse vorübergehend zur Wiederverwendung zwischenspeichern möchten, sollten Sie lokale Variablen verwenden. Stellen Sie sicher, dass sie den globalen Geltungsbereich nicht verschmutzen (das window -Objekt); Verwenden Sie var , damit die Variable nur lokal beibehalten wird.

%Vor%

Bearbeiten zum Hinzufügen:

Es gibt zwei verschiedene Arten von Variablen, auf die verwiesen wird. An das Objekt angehängte Variablen (auf die mit this.varname oder this['varname'] zugegriffen wird) und Variablen, die nur innerhalb des lokalen Bereichs existieren (die mit var varname deklariert und mit varname aufgerufen werden).

Jede Variable, die an das Objekt angehängt ist, ist öffentlich zugänglich und sollte verwendet werden, um Daten oder Persistenzen zwischen Funktionsaufrufen aufzudecken. Jede in der Funktion deklarierte Variable ist nur im Kontext der Funktion zugänglich und daher für die Funktion privat. Sie behalten keine Werte über Aufrufe hinweg bei, können jedoch dazu verwendet werden, Daten über Aufrufe von Unterfunktionen hinweg zu speichern.

Zwischen Block A und Block B ist Block A die bevorzugte Methode für die Interaktion mit den Daten eines Objekts, in den meisten Fällen jedoch eine Funktion führt eine größere Reihe von Operationen durch, die oft komplexere Verhaltensweisen beinhalten. Wenn die Funktion einen Callback enthält, der die Werte von this.a , this.b und this.c benötigt, müssen Aliase verwendet werden, um die Daten zu übergeben, da this sich zwischen den Kontexten ändert.

Dies wird% ce_de%, 1 und 2 nicht wie erwartet alarmieren

%Vor%

Diese Version wird :

%Vor%     
zzzzBov 15.08.2011 18:03
quelle
0

Wenn Sie die Objektstruktur leicht ändern können, versuchen Sie, die benötigten Eigenschaften in einen Container (z) zu setzen:

%Vor%     
Silkster 15.08.2011 18:03
quelle
0

1) Sie sollten Benutzer var verwenden, um die Variablen zu deklarieren, andernfalls werden sie global sein.

2) Ja, das Kopieren des Wertes kann Ihnen Zeit beim Tippen sparen UND wird schneller ausgeführt, da der Zugriff auf Objekteigenschaften keine wirklich billige Operation ist. JavaScript implementiert keine Arrays. Sie sind immer Hashes.

    
Marcelo 15.08.2011 18:04
quelle
0
%Vor%     
Juan Ayala 15.08.2011 18:04
quelle
0

Ich erwarte, dass Sie var in Block B vor jede Ihrer Variablendeklarationen stellen möchten. Andernfalls tun Sie etwas, das Sie wahrscheinlich nicht vorhatten. Anstatt den Wert auf eine Variable zu setzen, die ausschließlich der anonymen Funktion entspricht, die Sie der Eigenschaft f zuweisen, würden Sie den Wert für die Eigenschaften a, b, c auf dem globalen Objekt festlegen.

Ich erwarte, dass Sie var vor jede Variable a, b und c in der anonymen Funktion stellen möchten.

Laut dem von Nicholas Zakas geschriebenen Buch High Performance Javascript erwähnt er Kosten, die mit der Auflösung von Identifikatoren verbunden sind ( Nachschlagen des von Ihnen verwendeten Variablennamens). Er erklärt, dass lokale Variablen am wenigsten teuer sind, während globale Variablen am teuersten sind.

In Ihrem Beispiel (Block B) ohne die var ist das, was Sie tun, teuer. Wenn Sie var in place haben, ist das, was Sie tun, optimal für das Identifizieren von Bezeichnern.

Wenn Sie an der Aufführung von JS interessiert sind, schlage ich vor, dass Sie Nicholas Buch kaufen.

    
fifteen3 15.08.2011 18:19
quelle
0

Wenn Donald Knuth sagt: "Wir sollten kleine Wirkungsgrade vergessen, sagen wir etwa 97% der Zeit: vorzeitige Optimierung ist die Wurzel allen Übels", wäre er tot, würde er sich in seinem Grab umdrehen. Für mich selbst fühle ich mich wie das .

Pass auf, Jungs und Mädchen. Effizienz spielt keine Rolle! Es tut es einfach nicht!

Vergessen wir den totalen Wahnsinn wie @Pheonix - es heißt "Phoenix" BTW! - sich tatsächlich Gedanken über den Platz zu machen, den lokale Variablen einnehmen, die zurückgewonnen werden, sobald die Funktion aufhört , und sich nur auf die ursprüngliche Frage zu konzentrieren. Betrachten Sie das folgende Bit des Codes:

%Vor%

Auf meinem erbärmlichen, fünf Jahre alten Laptop steht, dass eine solche Dereferenzierung des Objekts 90 Nanosekunden dauert . Das bedeutet, Sie können es elf Millionen mal pro Sekunde tun. Wirst du es elf Millionen Mal machen? Wenn nicht, verbringe keine Sekunde damit, sich darüber Gedanken zu machen.

In der Regel ist es einfacher, den richtigen Code zu optimieren als den optimierten Code zu korrigieren. Schreiben Sie Ihren Code gut und benchmarken Sie ihn dann. Wenn es zu langsam ist, identifizieren Sie die Engpässe (die garantieren, dass Sie die Ergebnisse von Objektdereferenzen in lokalen Werten nicht verwerfen), und beseitigen Sie sie.

Wir bringen Sie nun zu Ihrer regelmäßigen Programmierung zurück.

    
Malvolio 15.08.2011 18:33
quelle
0

Wie es ist. Nein. Da Sie var nicht zum Deklarieren Ihrer Variablen verwenden, deklarieren Sie diese Variablen im globalen Bereich und nicht im lokalen Bereich.

Wenn Sie wiederholt auf eine Variable zugreifen, lohnt es sich, eine Kopie im lokalen Bereich zwischenzuspeichern. Dies liegt daran, dass Funktionen und Objekte eine Kette von Bereichen haben, die durchsucht werden müssen, wenn die Variable nicht im unmittelbaren Bereich verfügbar ist. Im folgenden Beispiel muss die innerste Funktion zuerst in ihrem lokalen Bereich suchen, dann den Bereich ihrer übergeordneten Funktion und schließlich im Bereich der äußersten Funktion, um i zu finden. Wenn i in diesem Bereich nicht vorhanden wäre, müsste auch der globale Bereich durchsucht werden.

%Vor%

Das Problem beim Zwischenspeichern von Variablen im lokalen Bereich ist, dass manchmal Code schwer lesbar wird und in fast jeder Situation die Lesbarkeit die Effizienz übertrifft (ein Computer ist viel besser im Umgang mit ineffizientem Code als ein Mensch beim Lesen von Code) ist schlecht geschrieben).

Deklarieren Sie Ihre Variablen oben in Ihrer Funktion

Wenn Sie wirklich auf Effizienz / Korrektheit achten, dann deklarieren Sie alle Ihre Variablen am Anfang der Funktion. Dies ermöglicht Javascript sehr effizient beim Erstellen des lokalen Bereichs der Funktion. Deklarationen, die sich tief in einer Funktion befinden, sind ineffizient, da JavaScript zunächst prüfen muss, ob im lokalen Bereich verfügbarer Speicherplatz verfügbar ist, und die Größe des Bereichs bei Bedarf ändern. Seien Sie gewarnt, auch wenn Sie Ihre Variablen nicht an der Spitze einer Funktion deklarieren, werden einige Compiler es für Sie tun, da es Teil der ECMA-Spezifikation ist - was zu einigen Fehler führen kann. Quelle

zB

%Vor%

Im Wesentlichen hat die JavaScript-Engine Ihren Code folgendermaßen kompiliert:

%Vor%

Korrigierte Version Ihres Codes (wenn Sie weitere Operationen mit a, b oder c durchführen wollten).

%Vor%     
Dunes 15.08.2011 18:56
quelle

Tags und Links