Gibt es einen Grund, das Schlüsselwort "var" in ES6 zu verwenden?


261

Babels Leitfaden zu ES6 sagt:

letist das neue var.

Anscheinend besteht der einzige Unterschied darin, dass varder Gültigkeitsbereich der aktuellen Funktion und letder Gültigkeitsbereich des aktuellen Blocks festgelegt wird . Diese Antwort enthält einige gute Beispiele .

Ich kann keinen Grund für die Verwendung varin ES6-Code erkennen. Selbst wenn Sie eine gegebene Variable auf die gesamte Funktion beschränken möchten, können Sie dies tun, letindem Sie die Deklaration am oberen Rand des Funktionsblocks platzieren. Dies ist das, was Sie tun sollten var, um den tatsächlichen Umfang anzugeben. Und wenn Sie etwas feiner in einem forBlock oder so etwas sehen wollen, dann können Sie das auch tun.

Mein Instinkt ist also, varbeim Schreiben von ES6-Code die Verwendung ganz einzustellen.

Meine Frage ist, irre ich mich dabei? Gibt es einen legitimen Fall, in dem vares vorzuziehen wäre let?


3
Ich habe dies noch nicht ausprobiert (da ich noch keinen ES6-Code schreibe), aber es scheint, dass die Verwendung vardieser Variablen als bewusster Indikator für die gesamte Funktion eine nützliche "selbstdokumentierende" Konvention sein könnte .
jfriend00

10
Wenn Sie eine letAnweisung ganz oben auf eine Funktion setzen, ist es meines Erachtens genauso offensichtlich, dass Sie beabsichtigten, sie auf die gesamte Funktion zu übertragen. Ich glaube nicht, dass die Verwendung vares klarer macht, als es einfach oben anzuordnen.
Callum

11
Ehrlich gesagt glaube ich, dass der einzige Grund, der varnoch besteht, die Abwärtskompatibilität ist. Wäre das nicht so gewesen, hätten sie alles weggenommen varoder gar nicht erst eingeführt letund stattdessen die Semantik vardahingehend geändert, wie es wohl die ganze Zeit hätte sein sollen.
Jörg W Mittag

2
@RayToal Ich bin mit 97% der Aussagen von Kyle Simpson einverstanden, aber seine Gründe für die weitere Verwendung varscheinen mir gering und reichen nicht aus, um eine dritte Art von Variable zu rechtfertigen, die herumspringt. Sie können eine letFunktion einfach auf eine ganze Funktion ausdehnen, indem Sie sie oben auf die Funktion setzen. Dies ist in der Absicht viel deutlicher als das Schreiben varin einen Block (damit sie aus diesem Block herausgezogen wird und Sie sie dann außerhalb des Blocks verwenden können) - seltsam). Er warnt davor, dass, wenn Sie eine letauf eine Funktion setzen, "es nur die Position ist, die den Unterschied signalisiert, und nicht die Syntax", aber ich denke, das ist eine gute Sache.
Callum

2
@RayToal Auch ich habe diesen Artikel gelesen (kurz bevor ich diese Diskussion gelesen habe) und ich war wirklich enttäuscht über seinen sehr schwachen Fall für var. Die Beispiele, die er zur Aufbewahrung vorstellt, varscheinen erfunden zu sein - und beruhen auf schwerwiegenden Codierungsfehlern. Es ist viel besser, auf einen Fehler zu stoßen und gezwungen zu sein, solche Fehler zu beheben, als Sprachfunktionen zu verwenden, mit denen man davonkommt! Was kommt als nächstes, raten Sie, alles in einen Versuch / Fang zu wickeln, um Abstürze zu vermeiden? Der Rest dieses Links ist gut, aber ich stimme diesem speziellen Teil überhaupt nicht zu.
Morre

Antworten:


217

Doug Crockford diskutiert letan dieser Stelle in seinem Vortrag " The Better Parts ".

Der Punkt ist, letvermeidet eine Quelle von Missverständnissen, insb. für Programmierer mit Erwartungen an Sprachen mit Blockumfang. A varhat einen Funktionsumfang (es deklariert eine Variable, die in der gesamten Funktion sichtbar ist), obwohl es aussieht, als hätte es einen Blockumfang .

var Vielleicht ist es im Extremfall, wie bei maschinengeneriertem Code, immer noch nützlich, aber ich bin sehr gespannt.

( constist ebenfalls neu und hat einen Blockbereich. Nachdem let x = {'hi': 'SE'}Sie neu zuweisen können x, während nachdem const y = xSie nicht neu yzuweisen können . Dies ist häufig vorzuziehen, da es verhindert, dass sich versehentlich etwas unter Ihnen ändert. Um klar zu sein, können Sie das Objekt jedoch ändern, es y.hi = 'SO'sei denn, Sie einfrieren.)

Realistisch gesehen stimmt Ihr Eindruck für ES6: Übernehmen letund const. Hör auf zu benutzen var.

(In einer anderen Aufführung von „The Better Parts“ , sagt Doug warum ===hinzugefügt wurde , anstatt zur Festsetzung der Probleme des== . ==Produziert einige „ überraschend“ Ergebnisse, also nur annehmen ===.)


Ein aufschlussreiches Beispiel

Mozilla Developer Network gibt ein Beispiel, in dem varnicht wie vorgesehen gearbeitet wird. Ihr Beispiel ist realistisch und setzt onclickHandler auf einer Webseite. Hier ist ein kleinerer Testfall:

var a = [];
(function () {
   'use strict';
   for (let i = 0; i < 5; ++i) { // *** `let` works as expected ***
     a.push( function() {return i;} );
   }
} ());
console.log(a.map( function(f) {return f();} ));
// prints [0, 1, 2, 3, 4]

// Start over, but change `let` to `var`.
// prints [5, 5, 5, 5, 5]

varschlägt fehl, weil alle Schleifeniterationen dieselbe funktionsbezogene iVariable verwenden, die 5nach Beendigung der Schleife den Wert hat .


6
Er gibt die gleiche Antwort über die Annahme von === anstelle von ==. Letzteres ist kaputt, aber das ES-Normungskomitee wollte es nicht ändern, also fügten sie hinzu . ==ist überhaupt nicht kaputt. Es kann einfach definiert werden als equality comparison using coersionCheck out github.com/getify/You-Dont-Know-JS/blob/master/…
AmmarCSE

13
@AmmarCSE, das ist ein wunderbares 39-seitiges Dokument über implizite Nötigungen. Wer kann das alles beim Programmieren beachten? Doug meinte "kaputt", wie in stackoverflow.com/a/359509/1682419 zusammengefasst , kurz gesagt, leicht zu bekommen, wenn Werttypen stärker variieren, als wir angenommen hatten. Können Sie all dies vorhersagen? [ '1.0' == 1.0, [1.0] == 1.0, [1.0] == '1.0', ['1.0'] == 1.0, [null] == '', [null] == 'null', '00' == false, [] == [], [] == 0, [] == '', [] == false, [] == true, [010] - [4] == ' 4.0 ', !![0], !![1], [0] == true, [1] == true, 1 == [[1]], 0 == [[0]], '1' == [1] ]
Jerry101

2
Richtig, die meisten dieser Beispiele enthalten einen Array-Operanden. Das Ergebnis ist leicht zu verstehen, wenn Sie sich mit toString befassen und wie es für Objekte implementiert ist . Wenn das jedoch mit kaputt gemeint ist, dann sehe ich vollkommen, woher das kommt. :-)
AmmarCSE

3
warum nicht const verwenden, wenn es nicht veränderlich ist - nur fragen? I meine, die wirkliche Wahl , es ist nicht zwischen letund varsondern zwischen let, varundconst
shabunc

4
varfunktioniert wie geplant, aber nicht wie viele Leute erwarten. Es ist ein Usability-Fehler, kein Implementierungsfehler.
Jerry101

12

Wenn Sie korrekten Code geschrieben haben, können Sie wahrscheinlich alle Anweisungen ohne semantische Änderungen varin letAnweisungen umwandeln .

letist vorzuziehen, weil dadurch der Bereich verringert wird, in dem ein Bezeichner sichtbar ist. Es ermöglicht uns, Variablen am Ort der ersten Verwendung sicher zu deklarieren.

constist vorzuziehen let. Verwenden Sie eine constDeklaration, es sei denn, Sie müssen eine Referenz mutieren . Dies hat alle Vorteile, letzusammen mit dem Reduzieren des Vorhandenseins von unitialisierten Variablen und dem Vereinfachen des Denkens über Code. Wenn Sie nicht sicher sind, ob Sie eine Referenz mutieren müssen, deklarieren Sie sie, constbis Sie dies ausdrücklich tun müssen.


5

Ich denke nicht unbedingt, dass Sie sich irren, aber es gibt Vorbehalte, var zu verwenden. Im Wesentlichen letsollte es Entwicklern helfen, die Dummheit von JavaScript zu umgehen, insbesondere bei Namenskonflikten. varEs scheint, dass es einen größeren Bereich hat, da es in den Funktionsbereich "Closes" wechseln möchte. Es wird Zeiten geben, in denen Sie var benötigen, z. B. wenn eine temporäre Variable im Bereich eines Blocks innerhalb einer Funktion verfügbar sein muss. Andernfalls lethilft das Bevorzugen von var Entwicklern bei Namenskonflikten. Was das Ganze angeht, ist es an der Zeit, ES6 einzuführen let.


3
Ein Temp varin einem Block ist innerhalb der gesamten Funktion verfügbar und nicht blockspezifisch. Es ist eine irreführende Funktion.
Jerry101

1

Ich stimme eher zu, dass in es6 nur "let" verwendet werden sollte. AFIK, wenn Sie ein "let" neu deklarieren, erzeugt einen Fehler (was gut ist), während Sie mit "var" einfach den Wert überschreiben (obwohl "strict mode" in es5 auch dafür sorgt).


-4

letbedeutet "Variable gleich lassen". Es ist eine Deklaration, mit anderen Worten, eine Initialisierung und Zuweisung.

Es existiert im Gegensatz dazu, constwas natürlich "konstant" bedeutet - was das Gegenteil von variabel ist.

Einige andere Sprachen verwenden beim Deklarieren ein Präfix für das eigentliche Objekt anstelle des Objekts (z. B. defeine Abkürzung für "Funktion definieren" - es fehlt vollständig der Punkt, an dem "def" steht).

Let fügt diese semantische Inkonsistenz Javascript hinzu.

Logischerweise könnte eine Konstante auch gleich etwas sein, da das Schlüsselwort "let" die Zuweisung von Speicher dient.

Das Problem tritt auf, weil das varSchlüsselwort, das zuvor eingeführt constwurde, unterstützt wurde, sodass die Abwärtskompatibilität vorschreibt, dass varkeine Variable erforderlich ist. (Es kann auch verwendet werden, um einen konstanten Wert zuzuweisen.)

Daher die Einführung letin die falsche Position. Um sicherzustellen, dass wir uns daran erinnern, dass dies lexikalisch falsch ist, haben sie auch beschlossen, den lexikalischen Umfang von letvs zu ändern var, sodass die Inkonsistenz beim Debuggen für uns an erster Stelle steht.

Mit anderen Worten, es letexistiert, weil die Leute (dh die Sprachbetreuer) der Meinung sind, dass Javascript zu konsistent ist, da sie alle seine Redewendungen und Eigenheiten beherrschen und mehr verlangen.

Randnotiz: Funktioniert varnicht in "Pfeil" -Blöcken, wenn Sie die Blöcke als Abschlüsse behandeln möchten (da dies varvor der Behandlung von Blöcken als Abschlüsse eingeführt wurde), aber let.


6
-1: pedantisch, wenig hilfreich und hauptsächlich meinungsbasiert.
Joel Mueller

Fijiaaron scherzt hier nur mit uns.
Jerry101

Ich bin mit Ihrer Abneigung gegen die lexikalische Form einverstanden, letda sie im Widerspruch zum Ton anderer Keywords in der gleichen Kategorie in JavaScript steht. Dies beantwortet jedoch nicht die Frage und ist nicht besonders gut formuliert. Abgestimmt
Aluan Haddad

3
letist nicht nur Entwickler, die mehr Komplexität wünschen. Dies ist intuitiv verständlicher, da beim Schleifen und Schließen von Variablen die Schließung den letzten Wert der Variablen beibehält. Wenn Sie dies jedoch über Lets tun, hat jede Schließung in der Schleife ihren eigenen Wert für let, a la das Beispiel von @ Jerry101 oben
TKoL
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.