Quanto dovrei usare 'let' vs 'const' in ES6?


214

Ho scritto molto codice ES6 per io.js di recente. Non c'è molto codice in natura da cui imparare, quindi mi sento come se stessi definendo le mie convenzioni.

La mia domanda è su quando utilizzare constvs let.

Ho applicato questa regola: se possibile, utilizzare const. Utilizzare solo letse si conosce che il suo valore deve cambiare. (Puoi sempre tornare indietro e cambiare a constin a letse in seguito si scopre che è necessario modificarne il valore.)

Il motivo principale di questa regola è che è facile da applicare in modo coerente. Non ci sono aree grigie.

Il fatto è, quando applico questa regola, in pratica il 95% delle mie dichiarazioni lo sono const. E questo mi sembra strano. Sto solo usando letcose come iin un forciclo, o occasionalmente per cose come i totali di Fibonacci accumulati (che non si presentano molto nella vita reale). Sono rimasto sorpreso da questo: risulta che il 95% delle "variabili" nel mio codice ES5 fino ad oggi erano per valori che non variano. Ma vedere in consttutto il mio codice mi sembra sbagliato in qualche modo.

Quindi la mia domanda è: va bene usare constcosì tanto? Dovrei davvero fare cose del genere const foo = function () {...};?

O dovrei riservarmi constper quel tipo di situazioni in cui stai codificando un letterale nella parte superiore di un modulo - il tipo che fai in maiuscolo, come const MARGIN_WIDTH = 410;?


7
Ho il sospetto che questa domanda sia principalmente basata sull'opinione pubblica ed è quindi probabile che sia chiusa, ma i miei 2 centesimi: va bene usare constcosì tanto.
jhominal

15
function foo() {...}è meglio di<anything> foo = function() {...}
OrangeDog

12
@OrangeDog Mi piacerebbe vedere la tua spiegazione per questo, poiché ho concluso esattamente il contrario. C'è un avvertimento che function foo() {...}può causare una leggera confusione durante il debug, a causa del sollevamento. Inoltre, la sua esistenza significa che abbiamo due costrutti che fanno la stessa cosa, ma uno di essi funziona solo in un contesto molto specifico. (È possibile utilizzare un'espressione di funzione ovunque esista un'espressione, ma è possibile utilizzare solo una dichiarazione di funzione a livello di istruzione.) Se si preferisce la brevità, il problema potrebbe essere che la sintassi dell'espressione di funzione utilizza l'intera parola function.
Appassionato del

11
Le tracce dello stack hanno il nome della funzione anziché anon. Il sollevamento è buono e ti consente di definire le funzioni in un ordine naturale, senza doversi preoccupare di non essere definito.
OrangeDog,

1
Questi sono buoni punti da tenere a mente, ma non sono ancora convinto. I debugger moderni fanno un buon lavoro nella scelta del nome visualizzato corretto per la tua funzione in base al simbolo a cui lo assegni (se presente - se non presente, puoi usare un'espressione di funzione denominata). La dichiarazione dell'ordine naturale delle funzioni è altamente soggettiva. Potrebbe essere ragionevole pensare che l'ordine naturale debba iniziare definendo i pezzi di base, e successivamente definire i pezzi che li usano.
Appassionato del

Risposte:


183

La mia risposta qui non è specifica per JavaScript.

Come regola empirica in qualsiasi lingua che mi consenta di farlo in modo semi-semplice, direi sempre di usare const / final / readonly / qualunque cosa venga chiamata nella tua lingua ogni volta che è possibile. Il motivo è semplice, è molto più facile ragionare sul codice quando è ovvio cosa può cambiare e cosa non può cambiare. Inoltre, in molte lingue puoi ottenere il supporto degli strumenti che ti dice che stai facendo qualcosa di sbagliato quando assegni accidentalmente una variabile che hai dichiarato const.

Tornare indietro e cambiare una const in una let è semplicissimo. E andare const di default ti fa pensare due volte prima di farlo. E questo è in molti casi una buona cosa.

Quanti bug hai riscontrato che le variabili coinvolte cambiano inaspettatamente? Immagino molto. So che la maggior parte dei bug che vedo coinvolgono cambiamenti di stato inaspettati. Non ti libererai di tutti questi bug usando liberamente const, ma ti sbarazzerai di molti di loro!

Inoltre, molti linguaggi funzionali hanno variabili immutabili in cui tutte le variabili sono const di default. Guarda Erlang per esempio, o F #. La codifica senza assegnazione funziona perfettamente in queste lingue ed è uno dei tanti motivi per cui le persone adorano la programmazione funzionale. C'è molto da imparare da queste lingue sulla gestione dello stato per diventare un programmatore migliore.

E tutto inizia con l'essere estremamente liberale con const! ;) Sono solo altri due personaggi da scrivere rispetto a let, quindi vai avanti e consttutto il resto!


45
constè due più personaggi di let...
OrangeDog

72
Ma 5 personaggi in meno di immutabili.
Cerad,

7
Sembra un po 'come usare valScala (che dichiara una variabile come immutabile) e usare solo var(l'equivalente mutabile) quando non possiamo usare val. In altre parole, dichiariamo le variabili come immutabili per impostazione predefinita e introduciamo la mutabilità solo quando ne abbiamo assolutamente bisogno (che può essere semplicemente perché l'approccio mutabile è più pulito).
Kat

7
Concordo con questa risposta, ma tengo presente che le cose non sono così ovvie quando si lavora con cose come oggetti semplici o array in quanto le loro proprietà possono cambiare anche se sono state definite con 'const'. Avevo pensato a "const" che funzionava come object.freeze ma non è così.
backdesk,

2
@Cerad Intendevi “4 caratteri in meno” o mi sto perdendo qualche battuta qui?
Mathias Bynens,

57

Fai attenzione, perché constle chiavi degli oggetti sono modificabili.

Da qui: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

le chiavi degli oggetti non sono protette

considera questo esempio:

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

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

Stessa cosa per gli array:

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

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

Non ho deciso totalmente me stesso, ma sto prendendo in considerazione l'utilizzo constper tutti i non array / non oggetti e l'uso letper oggetti / array.


34
IMO vero, ma previsto: ciò che è costante è il riferimento all'oggetto assegnato al tuo const. colors = numbersnon funzionerà, come previsto. Se si desidera proteggere le proprietà degli oggetti, è possibile utilizzare Object.freeze() developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Josef Engelfrost,

16
Ingannevole. È immutabile. Ma le proprietà dell'oggetto reale non lo sono.
Gaston Sanchez,

1
+1 Sì, il riferimento è protetto, ma in termini di domanda , è abbastanza sciocco da usare in casi come const moment = require('moment'), a meno che tu non sia il tipo di persona che è preoccupata che qualcuno proverà a fare in moment = dead.fish(() => pizza)seguito.
MaxWell,

5
Forse più realistico di cui preoccuparsi moment = Date.now(). Ma in ogni caso, se il codice assume un invariante, non vedo nulla di male nel farlo rispettare dove possibile.
James M.

3
Nessuno ha detto che non erano immutabili, però. È un malinteso comune che l'obiettivo di const è renderlo immutabile, quando è davvero garantire che il nome non farà mai riferimento a un oggetto diverso da quello a cui è stato inizializzato.
Monokrome,

25

Non ti preoccupare. constè un'aggiunta straordinaria a JavaScript e ti consiglierei di usarlo in tutti i posti che ha senso. Rende il codice più robusto.

Quando si tratta di oggetti, constproteggerai la tua variabile dalla riassegnazione, ma se hai bisogno di oggetti immutabili, avrai bisogno del Object.freezemetodo, vedi sotto.

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

constproteggerà solo dalla riassegnazione e il freezemetodo proteggerà tutte le proprietà immediate. Se è necessario che anche tutte le proprietà nidificate siano immutabili, è necessario ricorsivamente freeze.


14
Si noti che Object.freezeè poco profondo.
Mathias Bynens,

@MathiasBynens Mi sono imbattuto in questo commento e sono curioso di sapere cosa intendevi esattamente con questo. Potresti per favore elaborare?
Cole Roberts,

@ColeRoberts Il concetto di immutabilità superficiale è quando il riferimento dell'oggetto stesso è immutabile, ma le proprietà possono ancora essere modificate. La parola chiave const rende l'immutabilità superficiale, quindi è necessario utilizzare Object.freeze se anche tutte le proprietà devono essere immutabili.
clean_coding

3
@ColeRoberts Significa che i valori degli oggetti all'interno di un oggetto congelato (ad es. Oggetti nidificati) possono ancora essere mutati. Vedi mathiasbynens.be/notes/es6-const#immutable-values per maggiori informazioni.
Mathias Bynens,

19

Nel mio ES6 constnon si tratta di post sull'immutabilità , spiego cosa constsignifica esattamente secondo le specifiche.

Sulla base di questi fatti oggettivi, ecco la mia preferenza personale:

[…] Ha senso usare lete constcome segue nel tuo codice ES6:

  • utilizzare constper impostazione predefinita
  • utilizzare solo letse è necessario il rebinding (ovvero qualsiasi forma di riassegnazione)
  • ( varnon dovrebbe essere usato in ES6)

Per quanto soggettivo, è un dato di fatto che questo corrisponde più da vicino alle intenzioni della specifica.

Le persone che usano letper impostazione predefinita di solito trattano le constvariabili come costanti (che non sono necessariamente, di progettazione!). A ciascuno il suo, ma preferisco usare le cose per il loro scopo previsto, e non per un significato inventato che le persone assegnano ad esso in base a un malinteso.

Usare constsolo per le costanti è come usare l' <aside>elemento HTML solo per il contenuto della barra laterale.


2
Perché dovresti nominare qualcosa constse non è costante?
nu everest,

3
@nueverest Perché non constè quello che serve. Hai letto quanto sopra?
Mathias Bynens,

2
@MathiasBynens Penso che il (solo?) Problema constsia che si chiama const. È un nome stupido (in javascript) che inizialmente confonde molti (tutti?) Sviluppatori. Sarebbe meglio l'IMO se fosse conststato chiamato let(soprattutto perché letè più corto ma constmolto più comune) e letchiamato qualcos'altro.
MrN00b,

@MathiasBynens Ho capito, ma perché chiamarlo così? Sta creando un'enorme confusione, come dimostra questa pagina.
jtr13

4

Il mio approccio personale, pensato per aiutare la leggibilità e la comprensione del codice:


letè solo per variabili di breve durata, definite su una sola riga e non modificate dopo. Generalmente quelle variabili che sono lì solo per ridurre la quantità di battitura. Per esempio:

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]
  ...
}

constper tutti i nomi noti per essere costanti in tutto il modulo. Non inclusi i valori di costante locale. L' valueesempio sopra, ad esempio, ha una portata costante e potrebbe essere dichiarato con const, ma poiché ci sono molte iterazioni e per ognuna c'è un valore con lo stesso nome , "valore", che potrebbe indurre il lettore a pensare che valuesia sempre lo stesso. I moduli e le funzioni sono il miglior esempio di constvariabili:

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

varper tutto ciò che può essere o meno variabile. I nomi che possono confondere le persone che leggono il codice, anche se sono costanti a livello locale e per i quali non sono adatti let(ovvero non sono completati in una semplice dichiarazione diretta), si applicano per essere dichiarati con var. Per esempio:

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
}

Ulteriori commenti e possibili futuri aggiornamenti qui .


10
quel secondo frammento di codice sembra una pistola.
Giuliano

1

JavaScript è un po 'speciale in quanto le variabili possono essere funzioni e simili, ma si consideri in C #, Java o un altro linguaggio simile in stile C:

const public void DoSomething()

Il constè dispari, e questo perché le dichiarazioni di metodo in queste lingue non possono cambiare, una volta che sono compilati in qualcosa d'altro, che è quello che fanno, non importa quale (ignorando alcuni hack orribili che possono esistere).

Perché JavaScript dovrebbe essere diverso? Quindi non è compilato, ma ciò non significa che dovremmo buttare via la sicurezza che i compilatori possono fornire. L'uso della constparola chiave ci dà più sicurezza, il che porterà sicuramente ad applicazioni più robuste.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.