1661 Stimmen

Was ist der Zweck des var-Schlüsselworts und wann sollte ich es verwenden (oder weglassen)?

HINWEIS: Diese Frage wurde aus der Perspektive von ECMAScript-Version 3 oder 5 gestellt. Die Antworten könnten mit der Einführung neuer Funktionen im Release von ECMAScript 6 veraltet sein.

Was genau ist die Funktion des var-Schlüsselworts in JavaScript, und was ist der Unterschied zwischen

var someNumber = 2;
var someFunction = function() { doSomething; }
var someObject = { }
var someObject.someProperty = 5;

und

someNumber = 2;
someFunction = function() { doSomething; }
someObject = { }
someObject.someProperty = 5;

?

Wann würden Sie jeweils eines verwenden und warum/was macht es?

6 Stimmen

Wenn Sie Variablendeklarationen verketten, beeinflusst das Einfügen einer neuen Zeile nach einem Komma das Verhalten? var x=1, y=2, [return]z=3;

6 Stimmen

Das Unterlassen von "var" macht Sie auch anfällig, falls der Variablenname, den Sie gewählt haben, zufällig eine zuvor definierte globale Variable ist. Sehen Sie hier meine Trauerreise: stackoverflow.com/questions/16704014/…

7 Stimmen

Der Melonenkarten-Blogbeitrag von @Ray Toal (definitiv lesenswert) wurde auf blog.safeshepherd.com/23/how-one-missing-var-ruined-our-l‌aun‌​ch verschoben.

1409voto

Greg Punkte 306033

Wenn Sie im globalen Bereich sind, gibt es nicht viel Unterschied. Lesen Sie Kangax's Antwort zur Erklärung

Wenn Sie sich in einer Funktion befinden, erstellt var eine lokale Variable. "no var" sucht im Scope-Chain nach der Variable oder gelangt zum globalen Scope (und erstellt sie dann):

// Beide sind globale Variablen
var foo = 1;
bar = 2;

function()
{
    var foo = 1; // Lokal
    bar = 2;     // Global

    // Führen Sie eine anonyme Funktion aus
    (function()
    {
        var wibble = 1; // Lokal
        foo = 2; // Erbt vom darüberliegenden Scope (erstellt einen Closure)
        moo = 3; // Global
    }())
}

Wenn Sie keine Zuweisung vornehmen, müssen Sie var verwenden:

var x; // Deklariere x

35 Stimmen

Ist "nicht wirklich viel Unterschied" == "Kein Unterschied"?

69 Stimmen

Nun ja, tatsächlich gibt es einen Unterschied :) Ob dieser Unterschied wichtig ist, ist eine andere Frage. Siehe meine Antwort weiter unten: stackoverflow.com/questions/1470488/…

6 Stimmen

Ich denke, das könnte Alex' Standpunkt sein, deshalb hat er es unter Verwendung des "ist gleich" Operators geschrieben!

773voto

kangax Punkte 38303

Es gibt einen Unterschied.

var x = 1 deklariert Variable x im aktuellen Scope (auch Ausführungskontext genannt). Wenn die Deklaration innerhalb einer Funktion erfolgt, wird eine lokale Variable deklariert; befindet sie sich im globalen Scope, wird eine globale Variable deklariert.

x = 1 hingegen ist lediglich eine Eigenschaftszuweisung. Zuerst versucht es, x über den Scope-Chain aufzulösen. Wenn es sie irgendwo in diesem Scope-Chain findet, wird die Zuweisung durchgeführt; falls es x nicht findet, wird nur dann die Eigenschaft x auf einem globalen Objekt erstellt (welches das oberste Objekt im Scope-Chain ist).

Beachten Sie jetzt, dass es keine globale Variable deklariert, sondern eine globale Eigenschaft erstellt.

Der Unterschied zwischen den beiden ist subtil und kann verwirrend sein, es sei denn, Sie verstehen, dass Variable-Deklarationen auch Eigenschaften erstellen (nur auf einem Variablenobjekt) und dass jede Eigenschaft in Javascript (bzw. ECMAScript) bestimmte Flags hat, die ihre Eigenschaften beschreiben - ReadOnly, DontEnum und DontDelete.

Da die Variabledeklaration eine Eigenschaft mit dem Flag DontDelete erstellt, besteht der Unterschied zwischen var x = 1 und x = 1 (wenn sie im globalen Scope ausgeführt werden) darin, dass die erstere - die Variabledeklaration - die nicht löschbare Eigenschaft erstellt, und die letztere nicht. Als Konsequenz kann die über diese implizite Zuweisung erstellte Eigenschaft dann aus dem globalen Objekt gelöscht werden, und die erstere - die über die Variabledeklaration erstellte - kann nicht gelöscht werden.

Aber das ist natürlich nur Theorie, und in der Praxis gibt es noch mehr Unterschiede zwischen den beiden, aufgrund verschiedener Fehler in Implementierungen (wie die von IE).

Hoffentlich ergibt das alles Sinn : )


[Update 2010/12/16]

In ES5 (ECMAScript 5; kürzlich standardisiert, 5. Auflage der Sprache) gibt es einen sogenannten "Strict Mode" - ein optionaler Sprachmodus, der das Verhalten von nicht deklarierten Zuweisungen geringfügig ändert. Im Strict Mode führt eine Zuweisung an einen nicht deklarierten Bezeichner zu einem ReferenceError. Der Grund dafür war, versehentliche Zuweisungen zu erkennen und die Erstellung unerwünschter globaler Eigenschaften zu verhindern. Einige der neueren Browser haben bereits begonnen, Unterstützung für den Strict Mode zu implementieren. Siehe zum Beispiel meine Kompatibilitätstabelle.

0 Stimmen

Wenn ich mich richtig erinnere, glaube ich, dass ich einmal einen Weg gefunden habe, eine mit var deklarierte Variable mit einem gewissen eval Hack zu löschen . Wenn ich mich an den genauen Trick erinnere, werde ich ihn hier posten.

3 Stimmen

@Mageek Er könnte von eval-deklarierten Variablen sprechen, die löschbar sind. Ich habe einmal einen Blogpost darüber geschrieben.

1 Stimmen

Ein wenig abseits vom Thema, aber zur Referenz erwähnenswert. "let" ist sehr ähnlich zu "var" und wird von Mozilla unterstützt. Der Hauptunterschied besteht darin, dass der Geltungsbereich einer var-Variablen die gesamte umgebende Funktion ist, während "let" auf seinen Block beschränkt ist.

142voto

Jonathan Lonowski Punkte 116832

Zu sagen, es sei der Unterschied zwischen "lokal und global", ist nicht ganz genau.

Es ist vielleicht besser, es als den Unterschied zwischen "lokal und am nächsten" zu betrachten. Das Am nächstenliegende kann sicherlich global sein, aber das wird nicht immer der Fall sein.

/* globaler Bereich */
var lokal = true;
var global = true;

function äußerlich() {
    /* lokaler Bereich */
    var lokal = true;
    var global = false;

    /* am nächstenliegenden Bereich = äußerlich */
    lokal = !global;

    function innerlich() {
        /* am nächstenliegenden Bereich = äußerlich */
        lokal = false;
        global = false;

        /* am nächstenliegenden Bereich = undefiniert */
        /* standardmäßig wird eine globale Variable definiert */
        public = global;
    }
}

4 Stimmen

Ist der nächste Bereich outer, in dem du var global = false; definierst?

1 Stimmen

@Snekse: 'nearest' gilt nicht, wenn var global = false; deklariert wird. Bei dieser Deklaration wird 'global' in den Gültigkeitsbereich von outer() platziert, weil 'var' in der Deklaration verwendet wird. Da 'var' in inner() nicht verwendet wird, wird es den Wert auf der nächsten höheren Ebene ändern, die outer() ist.

1 Stimmen

Ich frage mich, ob dein Kommentar sich ändern würde, wenn du diese Zeile in var global = local; ändern würdest. In diesem Fall wäre der am nächsten gelegene Bereich von "local" der äußere Bereich, der aktiv definiert wird. Es wird jedoch merkwürdig, wenn du dieselbe Zeile in var global = global ändern würdest, in diesem Fall wäre der nächstgelegene Bereich beim Suchen nach dem Wert von global eine Ebene höher im globalen Fensterbereich.

85voto

kentaromiura Punkte 6369

Wenn Javascript in einem Browser ausgeführt wird, wird Ihr gesamter Code von einer with-Anweisung umgeben, wie folgt:

with (window) {
    //Ihr Code
}

Weitere Informationen zu with - MDN

Weil var eine Variable im aktuellen Scope deklariert, gibt es keinen Unterschied zwischen der Deklaration von var innerhalb von window und gar keiner Deklaration.

Der Unterschied tritt auf, wenn Sie sich nicht direkt in window befinden, z.B. innerhalb einer Funktion oder innerhalb eines Blocks.

Die Verwendung von var ermöglicht es Ihnen, externe Variablen mit demselben Namen zu verbergen. Auf diese Weise können Sie eine "private" Variable simulieren, aber das ist ein anderes Thema.

Ein Faustregel ist es, immer var zu verwenden, da sonst die Gefahr besteht, subtile Bugs einzuführen.

EDIT: Nach den erhaltenen Kritiken möchte ich Folgendes betonen:

  • var deklariert eine Variable im aktuellen Scope
  • Der globale Scope ist window
  • Wenn var nicht verwendet wird, wird var implizit im globalen Scope (window) deklariert
  • Die Deklaration einer Variablen im globalen Scope (window) mit var ist dasselbe wie das Weglassen
  • Die Deklaration einer Variablen in Scopes, die sich von window unterscheiden, mit var ist nicht dasselbe wie die Deklaration einer Variablen ohne var
  • Deklarieren Sie immer var explizit, denn das ist eine gute Praxis

3 Stimmen

Ich habe dich nicht negativ bewertet, aber Bereich ist wahrscheinlich ein besseres Wort als Fenster. Deine ganze Erklärung ist etwas schwer verständlich.

6 Stimmen

Ich nenne einfach Dinge mit ihrem Namen, du möchtest es „global scope“ nennen, das ist in Ordnung, aber auf der Client-Seite ist es nach Konvention das window-Objekt, das das letzte Element der Scope-Kette ist, deshalb kannst du jede Funktion und jedes Objekt im Fenster aufrufen, ohne "window." zu schreiben.

4 Stimmen

+1 das ist eine wirklich gute Erklärung - ich habe das var/no var Problem noch nie so eingerahmt (kein Wortspiel beabsichtigt) gehört.

51voto

Steve Harrison Punkte 111024

Verwenden Sie immer das var-Schlüsselwort, um Variablen zu deklarieren. Warum? Gute Codierungspraxis sollte an sich schon Grund genug sein, aber das Weglassen bedeutet, dass es im globalen Gültigkeitsbereich deklariert wird (eine Variable wie diese wird als "implizit" global bezeichnet). Douglas Crockford empfiehlt, niemals implizite Globale zu verwenden, und gemäß den Apple JavaScript Coding Guidelines:

Jede Variable, die ohne das var-Schlüsselwort erstellt wird, wird im globalen Gültigkeitsbereich erstellt und wird nicht vom Garbage Collector eingesammelt, wenn die Funktion zurückgibt (weil sie nicht aus dem Gültigkeitsbereich herausgeht), was die Möglichkeit eines Memory Leaks birgt.

21 Stimmen

"Gute Codierungspraxis" sollte niemals allein ausreichend sein. Es läuft darauf hinaus, dass "einige Leute im Internet gesagt haben, dass so mein Code aussehen sollte". Das ist sogar weniger gültig als "mein Lehrer hat gesagt", es sei denn, man versteht zumindest ansatzweise den Grund hinter der Regel.

0 Stimmen

@cHao Ich denke, dass gute Codierungspraxis immer ausreichender Grund ist, wenn es eine empfohlene bewährte Methode ist, was diese ist und von mehreren JavaScript-Autoren.

12 Stimmen

@ChrisS: Nein, "gute Codierungspraxis" ist nicht an sich ein Grund. Der Grund, warum es als gute Praxis betrachtet wird, ist das, was zählt. Es sei denn, diese Autoren sagen Ihnen, warum sie es empfehlen, sollte ihre Empfehlung überhaupt kein Gewicht haben. Wenn Sie nicht mit den Gründen einverstanden sind, dürfen Sie es als schlechten Rat betrachten. Und wenn Sie es befolgen, ohne jemals zu fragen warum, ist das der Beginn von Kultismus.

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