Wie oft sollte ich in ES6 'let' vs 'const' verwenden?

214

Ich habe in letzter Zeit viel ES6-Code für io.js geschrieben. In der Natur gibt es nicht viel Code, von dem ich lernen kann. Ich habe also das Gefühl, meine eigenen Konventionen zu definieren.

Meine Frage ist, wann man constvs benutzt let.

Ich habe diese Regel angewendet: Wenn möglich, benutze const. Nur verwenden, letwenn Sie wissen, dass sich der Wert ändern muss. (Sie können jederzeit zurückgehen und a constin a ändern , letwenn sich später herausstellt, dass Sie den Wert ändern müssen.)

Der Hauptgrund für diese Regel ist, dass es einfach ist, sie konsistent anzuwenden. Es gibt keine Grauzonen.

Die Sache ist, wenn ich diese Regel anwende, sind in der Praxis 95% meiner Erklärungen const. Und das sieht komisch für mich aus. Ich benutze es nur letfür Dinge wie iin einer forSchleife oder gelegentlich für Dinge wie angesammelte Fibonacci-Summen (was im wirklichen Leben nicht besonders häufig vorkommt). Das hat mich überrascht - es stellte sich heraus, dass 95% der 'Variablen' in meinem ES5-Code bis jetzt für Werte waren, die nicht variieren. Aber constüberall in meinem Code zu sehen, fühlt sich irgendwie falsch an.

Meine Frage lautet also: Ist es in Ordnung, so constviel zu verwenden? Sollte ich wirklich Dinge tun wie const foo = function () {...};?

Oder sollte ich constfür solche Situationen reservieren, in denen Sie ein Literal am Anfang eines Moduls fest programmieren - wie Sie es in Großbuchstaben tun const MARGIN_WIDTH = 410;?

Callum
quelle
7
Ich vermute, dass diese Frage in erster Linie meinungsbasiert ist und daher wahrscheinlich geschlossen wird, aber meine 2 Cent: Es ist in Ordnung, constso viel zu verwenden.
JHOMINAL
15
function foo() {...}ist besser als<anything> foo = function() {...}
OrangeDog
12
@OrangeDog Ich würde gerne Ihre Erklärung dafür sehen, da ich genau das Gegenteil festgestellt habe. Es gibt eine Einschränkung, function foo() {...}die beim Debuggen zu geringfügigen Verwirrungen führen kann. Außerdem bedeutet seine Existenz, dass wir zwei Konstrukte haben, die dasselbe tun, aber eines von ihnen funktioniert nur in einem sehr spezifischen Kontext. (Sie können einen Funktionsausdruck überall dort verwenden, wo ein Ausdruck existieren kann, aber Sie können nur eine Funktionsdeklaration auf Anweisungsebene verwenden.) Wenn Sie die Kürze bevorzugen, besteht das Problem möglicherweise nur darin, dass die Funktionsausdruckssyntax das ganze Wort verwendet function.
Keen
11
Stack-Traces haben anstelle von anon den Namen der Funktion. Das Heben ist gut und Sie können Funktionen in einer natürlichen Reihenfolge definieren, ohne sich Sorgen machen zu müssen, dass foo undefiniert ist.
OrangeDog
1
Das sind gute Punkte, aber ich bin noch nicht überzeugt. Moderne Debugger leisten gute Arbeit bei der Auswahl des richtigen Anzeigenamens für Ihre Funktion basierend auf dem Symbol, dem Sie ihn zuweisen (falls vorhanden - falls nicht, können Sie einen benannten Funktionsausdruck verwenden). Die natürliche Reihenfolge der Funktionsdeklaration ist sehr subjektiv. Es mag vernünftig sein zu glauben, dass die natürliche Reihenfolge darin besteht, zunächst die Grundstücke und später die Teile zu definieren, die sie verwenden.
Keen

Antworten:

183

Meine Antwort hier ist nicht Javascript-spezifisch.

Als Faustregel in jeder Sprache, die es mir erlaubt, dies auf eine einfache Art und Weise zu tun, würde ich sagen, benutze immer const / final / readonly / was auch immer es in deiner Sprache heißt, wann immer es möglich ist. Der Grund ist einfach, es ist viel einfacher, über Code zu urteilen, wenn es absolut offensichtlich ist, was sich ändern kann und was sich nicht ändern kann. Darüber hinaus können Sie in vielen Sprachen Tool-Unterstützung erhalten, die Ihnen mitteilt, dass Sie etwas falsch machen, wenn Sie versehentlich eine Variable zuweisen, die Sie als const deklariert haben.

Zurück zu gehen und eine Konstante in eine Let zu ändern, ist denkbar einfach. Und wenn Sie standardmäßig auf const umsteigen, überlegen Sie zweimal, bevor Sie dies tun. Und das ist in vielen Fällen gut so.

Wie viele Fehler haben Sie gesehen, bei denen sich Variablen unerwartet geändert haben? Ich würde viel raten. Ich weiß, dass die meisten Fehler, die ich sehe, unerwartete Zustandsänderungen beinhalten. Sie werden nicht alle diese Fehler loswerden, indem Sie großzügig const verwenden, aber Sie werden eine Menge von ihnen loswerden!

Viele funktionale Sprachen haben unveränderliche Variablen, bei denen standardmäßig alle Variablen const sind. Schauen Sie sich zum Beispiel Erlang oder F # an. Codierung ohne Zuweisung funktioniert in diesen Sprachen einwandfrei und ist einer der vielen Gründe, warum Menschen die funktionale Programmierung lieben. Um ein besserer Programmierer zu werden, muss man in diesen Sprachen viel über das Verwalten von Zuständen lernen.

Und alles beginnt damit, dass man mit const extrem liberal ist! ;) Es müssen nur noch zwei Zeichen geschrieben werden, verglichen mit let. Also los und constalles!

wasatz
quelle
45
constist zwei Zeichen mehr als let...
OrangeDog
72
Aber 5 Zeichen weniger als unveränderlich.
Cerad
7
Dies ähnelt der Verwendung valin Scala (die eine Variable als unveränderlich deklariert) und nur der Verwendung von var(dem veränderlichen Äquivalent), wenn wir es nicht verwenden können val. Mit anderen Worten, wir deklarieren Variablen standardmäßig als unveränderlich und führen Veränderlichkeit nur dann ein, wenn wir sie unbedingt benötigen (was möglicherweise einfach daran liegt, dass der Veränderlichkeitsansatz sauberer ist).
Kat
7
Ich stimme dieser Antwort zu, bedenke aber, dass die Dinge nicht so offensichtlich sind, wenn Sie mit einfachen Objekten oder Arrays arbeiten, da sich ihre Eigenschaften ändern können, selbst wenn sie mit 'const' definiert wurden. Ich hatte gedacht, dass 'const' wie object.freeze funktioniert, aber das ist nicht der Fall.
Backdesk
2
@Cerad Meinten Sie „4 Zeichen weniger“ oder vermisse ich hier einen Witz?
Mathias Bynens
57

Seien Sie vorsichtig, da constObjektschlüssel veränderbar sind.

Von hier aus: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

Objektschlüssel sind nicht geschützt

Betrachten Sie dieses Beispiel:

const colors = {red: "#f00"}; 
console.log(colors); // { "red": "#f00" }

colors.red = "#00f";
colors.green = "#0f0";
console.log(colors); // { "red": "#00f", "green": "#0f0" }

Gleiches gilt für Arrays:

const numbers = [1, 2, 3];
console.log(numbers); // [ 1, 2, 3 ]

numbers.push(4);
console.log(numbers); // [ 1, 2, 3, 4 ]

Ich habe mich noch nicht entschieden, aber ich überlege, ob ich constfür alle Nicht-Arrays / Nicht-Objekte und letfür Objekte / Arrays verwenden soll.

lax4mike
quelle
34
Richtig, aber erwartete IMO - was konstant ist, ist die Ihrem zugewiesene Objektreferenz const. colors = numberswird nicht funktionieren, wie erwartet. Wenn Sie Ihre Objekteigenschaften schützen möchten, können Sie Object.freeze() developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Josef Engelfrost 13.10.15
16
Irreführend. Es ist unveränderlich. Die tatsächlichen Objekteigenschaften sind es jedoch nicht.
Gaston Sanchez
1
+1 Ja, die Referenz ist geschützt, aber in Bezug auf die Frage ist es ziemlich dumm, sie in Fällen wie zu verwenden, es const moment = require('moment')sei denn, Sie sind der Typ, der sich Sorgen macht, dass jemand es später versuchen wird moment = dead.fish(() => pizza).
MaxWell
5
Vielleicht realistischer, sich Sorgen zu machen moment = Date.now(). Aber auf jeden Fall sehe ich, wenn der Code eine Invariante annimmt, nichts Falsches daran, ihn wo immer möglich durchzusetzen.
James M.
3
Niemand sagte jedoch, dass sie nicht unveränderlich seien. Es ist ein weit verbreitetes Missverständnis, dass das Ziel von const darin besteht, es unveränderlich zu machen, wenn wirklich sichergestellt werden soll, dass der Name niemals auf ein anderes Objekt verweist als das, auf das er initialisiert wurde.
Monokrom
25

Mach dir keine Sorgen. constist eine erstaunliche Ergänzung zu JavaScript, und ich würde empfehlen, dass Sie es an allen Orten verwenden, die es sinnvoll macht. Es sorgt für robusteren Code.

Wenn es um Objekte geht, constwird Ihre Variable vor einer Neuzuweisung geschützt. Wenn Sie jedoch unveränderliche Objekte benötigen, benötigen Sie die Object.freezeMethode (siehe unten).

const immutableOject = Object.freeze({immutableProperty: 'foo'});

constschützt nur vor Neuzuweisung, und die freezeMethode schützt alle unmittelbaren Eigenschaften. Wenn alle verschachtelten Eigenschaften auch unveränderlich sein müssen, müssen Sie sie rekursiv freezeausführen.

clean_coding
quelle
14
Beachten Sie, dass Object.freezeflach ist.
Mathias Bynens
@MathiasBynens Ich bin auf diesen Kommentar gestoßen und bin gespannt, was genau du damit gemeint hast. Könnten Sie bitte näher darauf eingehen?
Cole Roberts
@ColeRoberts Das Konzept der flachen Unveränderlichkeit besteht darin, dass die Objektreferenz selbst unveränderlich ist, die Eigenschaften jedoch noch geändert werden können. Das Schlüsselwort const sorgt nur für geringe Unveränderlichkeit. Daher müssen Sie Object.freeze verwenden, wenn alle Eigenschaften auch unveränderlich sein sollen.
clean_coding
3
@ColeRoberts Das bedeutet, dass Objektwerte in einem eingefrorenen Objekt (dh verschachtelten Objekten) weiterhin mutiert werden können. Weitere Informationen finden Sie unter mathiasbynens.be/notes/es6-const#immutable-values .
Mathias Bynens
19

In meinem ES6 constgeht es nicht um Unveränderlichkeit , ich erkläre was constgenau laut Spezifikation bedeutet.

Basierend auf diesen objektiven Fakten, hier ist meine persönliche Präferenz:

[…] Es ist sinnvoll, letund constwie folgt in Ihrem ES6-Code zu verwenden:

  • Verwendung constvon Standard
  • Nur verwenden, letwenn erneutes Binden (dh jede Form der Neuzuweisung) erforderlich ist
  • ( varsollte nicht in ES6 verwendet werden)

So subjektiv es auch sein mag, es ist eine Tatsache, dass dies der Absicht der Spezifikation am ehesten entspricht.

Personen, die letstandardmäßig constVariablen verwenden, behandeln diese normalerweise als Konstanten (was nicht unbedingt beabsichtigt ist!). Jedem sein eigenes, aber ich bevorzuge es, Dinge für den beabsichtigten Zweck zu verwenden und nicht für einen erfundenen Sinn, den Menschen aufgrund eines Missverständnisses zuweisen.

Die Verwendung constnur für Konstanten entspricht der Verwendung des HTML- <aside>Elements nur für Seitenleisteninhalte.

Mathias Bynens
quelle
2
Warum würden Sie etwas nennen, constwenn es nicht konstant ist?
Nu Everest
3
@nueverest Weil das nicht das constist, wofür es ist. Hast du das oben gelesen?
Mathias Bynens
2
@MathiasBynens Ich denke das (einzige?) Problem constist, dass es heißt const. Es ist ein blöder Name (in Javascript), der viele (alle?) Entwickler zuerst verwirrt. IMO wäre besser, wenn constman angerufen hätte let(vor allem, weil letes kürzer ist, aber constweitaus häufiger vorkommt) und letetwas anderes anrief .
MrN00b
@ MathiasBynens Ich bekomme es, aber warum nenne ich es so? Wie diese Seite zeigt, führt dies zu einer enormen Verwirrung.
JTR13
4

Mein persönlicher Ansatz, um die Lesbarkeit und das Verständnis des Codes zu verbessern:


letist nur für kurzlebige Variablen, die in einer einzelnen Zeile definiert und danach nicht mehr geändert werden. Im Allgemeinen die Variablen, die nur dazu dienen, die Anzahl der Eingaben zu verringern. Zum Beispiel:

for (let key in something) {
  /* we could use `something[key]` for this entire block,
     but it would be too much letters and not good for the
     fingers or the eyes, so we use a radically temporary variable
  */
  let value = something[key]
  ...
}

constfür alle Namen, von denen bekannt ist, dass sie über das gesamte Modul konstant sind. Ohne lokal konstante Werte. Das valueobige Beispiel hat beispielsweise einen konstanten Gültigkeitsbereich und könnte mit deklariert werden const, aber da es viele Iterationen gibt und für jede einen Wert mit dem gleichen Namen "value" gibt, könnte dies den Leser zum Denken valueverleiten das Gleiche. Module und Funktionen sind das beste Beispiel für constVariablen:

const PouchDB = require('pouchdb')
const instantiateDB = function () {}
const codes = {
  23: 'atc',
  43: 'qwx',
  77: 'oxi'
}

varfür alles, was variabel sein kann oder nicht. Namen, die Personen, die den Code lesen, verwirren können, auch wenn sie lokal konstant sind und für die sie nicht geeignet sind let(dh sie werden nicht in einer einfachen direkten Deklaration vervollständigt), gelten als deklariert mit var. Zum Beispiel:

var output = '\n'
lines.forEach(line => {
  output += '  '
  output += line.trim()
  output += '\n'
})
output += '\n---'

for (let parent in parents) {
  var definitions = {}
  definitions.name = getName(parent)
  definitions.config = {}
  definitions.parent = parent
}

Weitere Kommentare und mögliche zukünftige Updates hier .

Fiatjaf
quelle
10
das zweite Code-Snippet sieht aus wie eine Waffe.
Julian
1

JavaScript ist insofern etwas Besonderes, als Variablen Funktionen und ähnliches sein können, aber in C #, Java oder einer anderen ähnlichen Sprache im C-Stil berücksichtigen:

const public void DoSomething()

Das constist seltsam, und das liegt daran, dass Methodendeklarationen in diesen Sprachen sich nicht ändern können, sobald sie zu etwas anderem kompiliert wurden.

Warum sollte JavaScript anders sein? Es wird also nicht kompiliert, aber das bedeutet nicht, dass wir die Sicherheit, die Compiler bieten können, wegwerfen sollten. Die Verwendung des constSchlüsselworts gibt uns mehr Sicherheit, was sicherlich zu robusteren Anwendungen führen wird.

Joe
quelle