C'è qualche motivo per usare la parola chiave "var" in ES6?


261

La guida di Babel a ES6 dice:

letè il nuovo var.

Apparentemente l'unica differenza è che varviene portata alla funzione corrente , mentre letviene portata al blocco corrente . Ci sono alcuni buoni esempi in questa risposta .

Non riesco a vedere alcun motivo per utilizzare varnel codice ES6. Anche se si desidera estendere una determinata variabile all'intera funzione, è possibile farlo letinserendo la dichiarazione nella parte superiore del blocco funzione, che è ciò che si dovrebbe fare varcomunque per indicare l'ambito effettivo. E se vuoi mirare qualcosa di più finemente in un forblocco o qualcosa, puoi farlo anche tu.

Quindi il mio istinto è smettere di usarlo del vartutto quando si scrive il codice ES6.

La mia domanda è: mi sbaglio su questo? Esiste un caso legittimo in cui varsarebbe preferibile rispetto a let?


3
Non l'ho ancora provato (dal momento che non sto ancora scrivendo il codice ES6), ma sembra che l'uso varcome indicatore consapevole che questa variabile sia destinata a essere portata all'intera funzione potrebbe essere un'utile convenzione di "auto-documentazione" .
jfriend00,

10
Se metti letun'istruzione proprio all'inizio di una funzione, penso che sia altrettanto ovvio che hai intenzione di estenderla all'intera funzione. Non credo che l'uso lo varrenda più chiaro del semplice localizzarlo in alto.
callum,

11
Onestamente, credo che l'unica ragione varesista ancora, sia la retrocompatibilità. Se non fosse stato per quello, avrebbero rimosso del vartutto, o mai introdotto letin primo luogo, cambiando invece la semantica di varciò che probabilmente avrebbe dovuto essere da sempre.
Jörg W Mittag,

2
@RayToal Sono d'accordo con il 97% di ciò che dice Kyle Simpson, ma i suoi motivi per continuare a usarmi mi sembrano scarsi var, e non abbastanza da giustificare un terzo tipo di variabile che salta in giro. Puoi mirare leta un'intera funzione semplicemente posizionandola nella parte superiore della funzione, che è molto più chiara nell'intento rispetto alla scrittura varin un blocco (per farla sollevare da quel blocco in modo da poterlo usare fuori dal blocco - strano). Egli avverte che se si esegue l'ambito leta una funzione, "è solo la posizione che segnala la differenza, piuttosto che la sintassi", ma penso che sia una buona cosa.
callum,

2
@RayToal Anche io ho letto quell'articolo (poco prima di leggere questa discussione) e sono rimasto davvero deluso per il suo caso molto debole var. gli esempi che presenta per mantenere varsembrano inventati e si basano su gravi errori di codifica. È molto meglio incorrere in un errore ed essere costretti a correggere tali errori piuttosto che utilizzare le funzioni del linguaggio che consentono di cavarsela! Qual è il prossimo, consiglia di avvolgere tutto in un tentativo / cattura per evitare arresti anomali? Il resto di quel link è buono ma non sono affatto d'accordo con quella parte particolare.
Mörre,

Risposte:


217

Doug Crockford discute leta questo punto nel suo discorso, " Le parti migliori ".

Il punto è, letevita una fonte di incomprensioni, esp. per programmatori con aspettative stabilite da linguaggi con ambito di blocco. A varha un ambito di funzione (dichiara una variabile che è visibile in tutta la funzione) anche se sembra che abbia un ambito di blocco .

var potrebbe essere ancora utile in un caso estremo come il codice generato dalla macchina, ma mi sto allungando molto.

( constè anche nuovo e ha un ambito di blocco. Dopo let x = {'hi': 'SE'}che puoi riassegnarti a x, mentre dopo const y = xnon puoi riassegnarti a y. Questo è spesso preferibile poiché impedisce a qualcosa di cambiare accidentalmente da sotto di te. Ma per essere chiari, puoi comunque modificare l'oggetto a y.hi = 'SO'meno che tu non congelalo.)

Realisticamente, la tua impressione è giusta per ES6: adottare lete const. Smetti di usare var.

(In un'altra interpretazione di "The Better Parts" , Doug dice perché è ===stato aggiunto piuttosto che risolvere i problemi di== . ==Produce alcuni risultati "sorprendenti", quindi basta adottare ===.)


Un esempio rivelatore

Mozilla Developer Network fornisce un esempio in cui varnon funziona come previsto. Il loro esempio è realistico che imposta i onclickgestori in una pagina Web. Ecco un test case più piccolo:

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]

varci fallisce perché tutte le iterazioni del ciclo condividono la stessa ivariabile con ambito funzionale , che ha il valore al 5termine del ciclo.


6
Dà la stessa risposta sull'adozione di === invece di ==. Quest'ultimo è rotto ma il comitato per le norme ES non ha voluto cambiarlo, quindi hanno aggiunto === Non sono sicuro di cosa significhi. ==non è affatto rotto. Può essere semplicemente definito come equality comparison using coersion
Dai

13
@AmmarCSE è un meraviglioso documento di 39 pagine sulle coercizioni implicite. Chi può tenere a mente tutto ciò durante la programmazione? Doug significava "rotto", come riassunto in stackoverflow.com/a/359509/1682419 , in breve, facile da ottenere quando i tipi di valore variano più di quanto si supponesse. Puoi prevedere tutto questo? [ '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
giusto, la maggior parte di quegli esempi coinvolge un operando di array. È facile capire il risultato quando si guarda a String e come viene implementato per gli oggetti . Tuttavia, se questo è ciò che si intende per rotto, allora vedo completamente da dove proviene. :-)
AmmarCSE,

3
perché non usare const ogni volta che non è mutabile - basta chiedere? Voglio dire, la vera scelta non è tra lete varma piuttosto tra let, vareconst
shabunc il

4
varfunziona come previsto, ma non quante persone si aspettano. È un bug di usabilità, non un bug di implementazione.
Jerry101,

12

Se hai scritto il codice corretto, probabilmente sarai in grado di trasformare tutte le varistruzioni in letistruzioni senza modifiche semantiche.

letè preferibile perché riduce l'ambito in cui è visibile un identificatore. Ci consente di dichiarare in modo sicuro le variabili nel sito di primo utilizzo.

constè preferibile let. A meno che non sia necessario mutare un riferimento, utilizzare una constdichiarazione. Ciò ha tutti i vantaggi di letridurre la presenza di variabili unitarie e rendere il codice generalmente più facile da ragionare. Se non sei sicuro di dover mutare un riferimento, dichiaralo constfino a quando non ti ritroverai esplicitamente necessario farlo.


5

Non penso necessariamente che ti sbagli, ma ci sono avvertenze sull'uso di var. In sostanza, letdovrebbe aiutare gli sviluppatori a aggirare la stupidità di JavaScript, in particolare con i conflitti di denominazione. var, a quanto pare, ha un ambito più ampio poiché desidera passare all'ambito della funzione di chiusura. Ci saranno momenti in cui hai bisogno di var, come quando hai bisogno di una variabile temp per essere disponibile nell'ambito di un blocco all'interno di una funzione, altrimenti, preferire letover var aiuterà gli sviluppatori con conflitti di denominazione. Su una nota più leggera, è giunto il momento di introdurre ES6 let.


3
varAll'interno dell'intera funzione è disponibile una temperatura in un blocco, non con ambito di blocco. È una caratteristica fuorviante.
Jerry101,

1

Tendo a concordare sul fatto che solo "let" dovrebbe essere usato in es6. AFIK, la redeclaration di una "let" genera un errore (il che è buono), mentre con "var", semplicemente si ignora il valore (anche se "modalità rigorosa" in es5 si occupa anche di quello).


-4

letsignifica "lasciare variabile uguale". È una dichiarazione, in altre parole, un'inizializzazione e un incarico.

Esiste in contrasto con il constquale ovviamente significa "costante" - che è l'opposto della variabile.

Alcuni altri linguaggi usano un prefisso per l'oggetto reale anziché l'oggetto quando lo dichiarano (ad esempio defè una scorciatoia per "definire la funzione" - manca completamente il punto di ciò che è "def".

Let aggiunge questa incoerenza semantica a Javascript.

Logicamente, potresti anche lasciare che una costante eguagli qualcosa, poiché il compito della parola chiave "let" è assegnare memoria.

Il problema sorge perché la varparola chiave è stata introdotta prima che constfosse supportata, quindi la compatibilità all'indietro impone che varnon significhi necessariamente una variabile. (Potrebbe anche essere usato per assegnare un valore costante.)

Quindi, l'introduzione di letnella posizione sbagliata. Per essere sicuri di ricordare che, dal punto di vista lessicale, questo è sbagliato, hanno anche deciso di cambiare l'ambito lessicale di letvs var, quindi l'incongruenza è soprattutto nelle nostre menti durante il debug.

In altre parole, letesiste perché le persone (intendendo i manutentori della lingua) pensavano che Javascript fosse troppo coerente, avendo imparato tutti i suoi idiomi e idiosincrasie, desiderando di più.

Nota a margine, varnon funziona nei blocchi "freccia" se si desidera trattare tali blocchi come chiusure (perché è varstato introdotto prima di trattare i blocchi come chiusure), ma letfunziona.


6
-1: pedante, inutile e principalmente basato sull'opinione pubblica.
Joel Mueller,

fijiaaron ci sta solo scherzando.
Jerry101,

Sono d'accordo con la tua antipatia per la forma lessicale letperché è in contrasto con il tono di altre parole chiave nella stessa categoria in JavaScript. Tuttavia, questo non risponde alla domanda e non è particolarmente ben posto. Downvoted
Aluan Haddad,

3
letnon sono solo gli sviluppatori che desiderano più complessità. In realtà è intuitivamente più comprensibile, perché quando si esegue il loop-and-close su var, la chiusura mantiene l'ultimo valore di var, ma quando si fa lo stesso su let, ogni chiusura nel loop ha il suo valore per let, a l'esempio di @ Jerry101 sopra
TKoL
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.