Dieses Phänomen ist bekannt als: JavaScript Variable Hoisting .
Sie greifen zu keinem Zeitpunkt auf die globale Variable in Ihrer Funktion zu. Sie greifen immer nur auf die lokale value
Variable zu.
Ihr Code entspricht dem Folgenden:
var value = 10;
function test() {
var value;
console.log(value);
value = 20;
console.log(value);
}
test();
Immer noch überrascht, dass Sie bekommen undefined
?
Erläuterung:
Dies ist etwas, auf das jeder JavaScript-Programmierer früher oder später stößt. Einfach ausgedrückt, was auch immer Variablen deklarieren Sie sind immer hochgezogen an die Spitze Ihrer lokalen Schließung. Obwohl Sie Ihre Variable nach dem ersten console.log
Aufruf deklariert haben , wird immer noch davon ausgegangen, dass Sie sie zuvor deklariert haben.
Es wird jedoch nur der Deklarationsteil gehisst; die Zuordnung ist dagegen nicht.
Als Sie das erste Mal aufgerufen haben console.log(value)
, haben Sie auf Ihre lokal deklarierte Variable verwiesen, der noch nichts zugewiesen wurde. daher undefined
.
Hier ist ein weiteres Beispiel :
var test = 'start';
function end() {
test = 'end';
var test = 'local';
}
end();
alert(test);
Was glaubst du, wird dies alarmieren? Nein, lesen Sie nicht einfach weiter, denken Sie darüber nach. Was ist der Wert von test
?
Wenn Sie etwas anderes sagten als start
, haben Sie sich geirrt. Der obige Code entspricht diesem:
var test = 'start';
function end() {
var test;
test = 'end';
test = 'local';
}
end();
alert(test);
so dass die globale Variable nie betroffen ist.
Wie Sie sehen, wird Ihre Variablendeklaration unabhängig davon, wo Sie sie ablegen, immer an die Spitze Ihres lokalen Verschlusses gehisst .
Randnotiz:
Dies gilt auch für Funktionen.
Betrachten Sie diesen Code :
test("Won't work!");
test = function(text) { alert(text); }
Das gibt Ihnen einen Referenzfehler:
Nicht erfasster ReferenceError: Test ist nicht definiert
Dies wirft viele Entwickler ab, da dieser Code gut funktioniert:
test("Works!");
function test(text) { alert(text); }
Der Grund dafür ist, wie angegeben, dass der Zuordnungsteil nicht angehoben wird. Im ersten Beispiel, als test("Won't work!")
es ausgeführt wurde, wurde die test
Variable bereits deklariert, ihr muss jedoch noch die Funktion zugewiesen werden.
Im zweiten Beispiel verwenden wir keine Variablenzuweisung. Vielmehr verwenden wir die richtige Funktionsdeklaration Syntax, die tut die Funktion bekommen vollständig gehisst.
Ben Cherry hat dazu einen ausgezeichneten Artikel mit dem passenden Titel JavaScript Scoping and Hoisting geschrieben .
Lies es. Sie erhalten das gesamte Bild im Detail.
Ich war etwas enttäuscht, dass das Problem hier erklärt wird, aber niemand schlug eine Lösung vor. Wenn Sie auf eine globale Variable im Funktionsumfang zugreifen möchten, ohne dass die Funktion zuerst eine undefinierte lokale Variable erstellt, verweisen Sie auf die Variable als
window.varName
quelle
Variablen in JavaScript haben immer einen funktionsweiten Bereich. Auch wenn sie in der Mitte der Funktion definiert wurden, sind sie vorher sichtbar. Ähnliche Phänomene können beim Funktionsheben beobachtet werden.
Davon abgesehen
console.log(value)
sieht die erste dievalue
Variable (die innere, die die äußere beschattetvalue
), aber sie wurde noch nicht initialisiert. Sie können sich vorstellen, dass alle Variablendeklarationen implizit an den Anfang der Funktion verschoben wurden ( nicht innerste Codeblock), während die Definitionen an derselben Stelle verbleiben.Siehe auch
quelle
Es gibt eine globale Variable
value
, aber wenn die Steuerung in dietest
Funktion eintritt , wird eine anderevalue
Variable deklariert, die die globale schattiert. Da Variablendeklarationen ( aber keine Zuweisungen ) in JavaScript an den Anfang des Bereichs gehoben werden, in dem sie deklariert werden:Beachten Sie, dass dies auch für Funktionsdeklarationen gilt. Dies bedeutet, dass Sie eine Funktion aufrufen können, bevor sie in Ihrem Code definiert zu sein scheint:
Es ist auch erwähnenswert, dass, wenn Sie die beiden zu einem Funktionsausdruck kombinieren, die Variable so lange ist,
undefined
bis die Zuweisung erfolgt, sodass Sie die Funktion erst dann aufrufen können, wenn dies geschieht:quelle
Der einfachste Weg, den Zugriff auf äußere Variablen (nicht nur von globalem Umfang) beizubehalten, besteht natürlich darin, zu versuchen, sie in Funktionen nicht unter demselben Namen erneut zu deklarieren. benutze dort einfach nicht var . Die Verwendung geeigneter beschreibender Namensregeln wird empfohlen. Bei diesen wird es schwierig sein, Variablen mit dem Namen value zu erhalten (dieser Aspekt hängt nicht unbedingt mit dem Beispiel in der Frage zusammen, da dieser Variablenname möglicherweise der Einfachheit halber angegeben wurde).
Wenn die Funktion an anderer Stelle wiederverwendet werden kann und daher nicht garantiert werden kann, dass die äußere Variable tatsächlich in diesem neuen Kontext definiert ist, kann die Eval- Funktion verwendet werden. Dieser Vorgang ist langsam und wird daher nicht für leistungsintensive Funktionen empfohlen:
Wenn die äußere Bereichsvariable, auf die Sie zugreifen möchten, in einer benannten Funktion definiert ist, wird sie möglicherweise zuerst an die Funktion selbst angehängt und dann von einer beliebigen Stelle im Code aus aufgerufen - sei es von tief verschachtelten Funktionen oder Ereignishandlern außerhalb von alles andere. Beachten Sie, dass der Zugriff auf Eigenschaften viel langsamer ist und Sie die Art und Weise Ihrer Programmierung ändern müssen. Daher wird dies nicht empfohlen, es sei denn, dies ist wirklich erforderlich: Variablen als Eigenschaften von Funktionen (JSFiddle) :
quelle
Ich hatte sogar mit globalen Variablen das gleiche Problem. Ich stellte fest, dass mein Problem darin bestand, dass globale Variablen zwischen HTML-Dateien nicht bestehen bleiben.
Ich habe versucht, myVar und myVarTwo in der geladenen HTML-Datei zu referenzieren, aber den undefinierten Fehler erhalten. Lange Rede / kurzer Tag, ich entdeckte, dass ich die Variablen mit folgenden Referenzen referenzieren konnte:
quelle