Existe algum motivo para usar a palavra-chave "var" no ES6?

261

O guia de Babel para o ES6 diz:

leté o novo var.

Aparentemente, a única diferença é o varescopo da função atual , enquanto o letescopo do bloco atual . Existem alguns bons exemplos nesta resposta .

Não vejo nenhum motivo para usar varno código ES6. Mesmo que você queira escopo uma dada variável para toda a função, você pode fazê-lo letcolocando a declaração na parte superior do bloco de funções, que é o que você deve fazer varpara indicar o escopo real. E se você deseja definir algo mais finamente em um forbloco ou algo assim, também pode fazer isso.

Então, meu instinto é parar de usar varcompletamente ao escrever o código ES6.

Minha pergunta é: estou errado sobre isso? Existe algum caso legítimo em varque seria preferível let?

callum
fonte
3
Ainda não tentei isso (já que ainda não estou escrevendo o código ES6), mas parece que usar varcomo um indicador consciente de que essa variável deve ter escopo definido para toda a função pode ser uma convenção útil de "auto-documentação" .
jfriend00
10
Se você colocar uma letdeclaração no topo de uma função, acho óbvio que você pretendia colocá-la em escopo para toda a função. Eu não acho que usar o vartorna mais claro do que simplesmente localizá-lo no topo.
Callum
11
Honestamente, acredito que a única razão varainda existe, é a compatibilidade com versões anteriores. Se não fosse por isso, eles teriam sido varcompletamente removidos , ou nunca introduzidos, letem vez disso, mudando a semântica varpara o que deveria ter sido o tempo todo.
Jörg W Mittag
2
@RayToal Eu concordo com 97% do que Kyle Simpson diz, mas seus motivos para continuar usando varparecem pequenos para mim, e não o suficiente para garantir um terceiro tipo de variável que se destaca. Você pode definir um escopo letpara uma função inteira simplesmente colocando-a na parte superior da função, o que é muito mais claro do que escrever varem um bloco (para que seja içada desse bloco para que você possa usá-lo fora do bloco) - esquisito). Ele alerta que, se você escopo leta uma função, "é apenas a posição que sinaliza a diferença, em vez da sintaxe", mas acho que é uma coisa boa.
Callum
2
@ RayToal Eu também li esse artigo (pouco antes de ler esta discussão) e fiquei muito decepcionado por seu argumento muito fraco var. os exemplos que ele apresenta para manter varparecem inventados - e são baseados em graves erros de codificação. É muito melhor encontrar um erro e ser forçado a corrigi-lo do que usar as funções de linguagem que permitem escapar impune! O que vem a seguir, aconselhe a agrupar tudo em uma tentativa / captura para evitar falhas? O restante desse link é bom, mas não concordo com essa parte em particular.
Morre

Respostas:

217

Doug Crockford discute leta este ponto em sua palestra, " as melhores partes ".

O ponto é, letevita uma fonte de mal-entendido, esp. para programadores com expectativas definidas por idiomas com escopo de bloco. A varpossui escopo de função (declara uma variável visível em toda a função), embora pareça ter escopo de bloco .

var ainda pode ser útil em casos extremos, como código gerado por máquina, mas estou me esforçando bastante por lá.

( consttambém é novo e tem escopo de bloco. Depois que let x = {'hi': 'SE'}você pode reatribuir a x, e depois que const y = xvocê não pode reatribuir a yisso. Isso geralmente é preferível, pois impede que algo mude acidentalmente sob você. Mas, para ser claro, você ainda pode modificar o objeto, a y.hi = 'SO'menos congele.)

Realisticamente, sua impressão está certa no ES6: Adote lete const. Pare de usar var.

(Em outra apresentação de "The Better Parts" , Doug diz por que ===foi adicionado ao invés de corrigir os problemas de== . ==Produz alguns resultados "surpreendentes", então adote ===.)


Um Exemplo Revelador

A Mozilla Developer Network fornece um exemplo em varque não funciona como pretendido. O exemplo deles é realista, que define onclickmanipuladores em uma página da web. Aqui está um caso de teste menor:

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]

varfalha conosco porque todas as iterações de loop compartilham a mesma ivariável com escopo de função , que tem o valor 5após o término do loop.

Jerry101
fonte
6
Ele dá a mesma resposta sobre a adoção de === em vez de ==. O último está quebrado, mas o comitê de padrões da ES não queria alterá-lo, então eles adicionaram === Não tenho muita certeza do que isso significa. ==não está quebrado. Ele pode ser simplesmente definido como equality comparison using coersionConfira github.com/getify/You-Dont-Know-JS/blob/master/…
AmmarCSE
13
@AmmarCSE que é um documento maravilhoso de 39 páginas sobre coerções implícitas. Quem pode manter tudo isso em mente durante a programação? Doug significava "quebrado", como resumido em stackoverflow.com/a/359509/1682419 , em suma, fácil de obter bits quando os tipos de valor variam mais do que presumíamos. Você pode prever tudo isso? [ '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
certo, a maioria desses exemplos envolve um operando de matriz. É fácil entender o resultado quando você examina o toString e como ele é implementado para objetos . No entanto, se é isso que significa " quebrado" , vejo completamente de onde isso vem. :-)
AmmarCSE
3
por que não usar const sempre que não é mutável - apenas perguntando? Quer dizer, a verdadeira escolha não é entre lete varmas entre let, vareconst
shabunc
4
varfunciona como projetado, mas não quantas pessoas esperam. É um bug de usabilidade, não um bug de implementação.
precisa saber é o seguinte
12

Se você tiver escrito o código correto, provavelmente poderá transformar todas as varinstruções em letinstruções sem nenhuma alteração semântica.

leté preferível porque reduz o escopo em que um identificador é visível. Ele nos permite declarar variáveis ​​com segurança no local do primeiro uso.

consté preferível let. A menos que você precise alterar uma referência, use uma constdeclaração. Isso tem todos os benefícios de letreduzir a presença de variáveis ​​unitializadas e tornar o código geralmente mais fácil de raciocinar. Se você não tiver certeza se precisará alterar uma referência, declare-a constaté que você se encontre explicitamente precisando fazer isso.

Aluan Haddad
fonte
5

Eu não necessariamente acho que você está errado, mas há advertências sobre o uso de var. Essencialmente, letdeve ajudar os desenvolvedores a contornar a estupidez do JavaScript, principalmente com conflitos de nomes. var, parece, tem um escopo maior, pois deseja ir para o escopo da função de fechamento. Haverá momentos em que você precisará de var, como quando você precisa que uma variável temp esteja disponível no escopo de um bloco dentro de uma função; caso contrário, preferir letao invés de var ajudará os desenvolvedores a conflitos de nomenclatura. Em uma nota mais clara, já era hora de o ES6 apresentar let.

curiousdork
fonte
3
Uma temperatura varem um bloco está disponível dentro de toda a função, sem escopo no bloco. É um recurso enganoso.
Jerry101
1

Costumo concordar que apenas "let" deve ser usado em es6. AFIK, redeclarar um "let" gera um erro (o que é bom), enquanto que com "var", você simplesmente substitui o valor (embora o "modo estrito" no es5 também cuide disso).

yar1
fonte
-4

letsignifica "deixar variável igual". É uma declaração, em outras palavras, uma inicialização e atribuição.

Existe em contraste com o constque, obviamente, significa "constante" - que é o oposto da variável.

Algumas outras linguagens usam um prefixo para o objeto real em vez do objeto ao declará-lo (por exemplo, defé uma abreviação de "define função" - faltando completamente o ponto do que está sendo "def".

Let adiciona essa inconsistência semântica ao Javascript.

Logicamente, você também pode deixar uma constante igual a algo, já que o trabalho da palavra-chave "let" é atribuir memória.

O problema surge porque a varpalavra - chave foi introduzida antes constera suportada; portanto, a compatibilidade com versões anteriores exige que varnão seja necessário uma variável. (Também pode ser usado para atribuir um valor constante.)

Daí, a introdução de letna posição errada. Para garantir que lembremos que, lexicamente, isso está errado, eles também decidiram alterar o escopo lexical de letvs var, de modo que a inconsistência é a principal em nossas mentes ao depurar.

Em outras palavras, letexiste porque as pessoas (ou seja, os mantenedores da linguagem) pensavam que o Javascript era muito consistente, tendo dominado todas as expressões idiomáticas e idiossincrasias, desejando mais.

Nota lateral, varnão funciona em blocos com "setas" se você deseja tratar os referidos blocos como fechamentos (porque varfoi introduzido antes de tratar os blocos como fechamentos), mas letfunciona.

fijiaaron
fonte
6
-1: pedante, inútil e principalmente baseado em opiniões.
Joel Mueller
fijiaaron está apenas brincando conosco aqui.
Jerry101
Sou solidário com o seu desagrado com a forma lexical letporque ela está em desacordo com o tom de outras palavras-chave da mesma categoria no JavaScript. Ainda assim, isso não responde à pergunta e não é particularmente bem colocado. Downvoted
Aluan Haddad
3
letnão são apenas desenvolvedores que desejam mais complexidade. Na verdade, é intuitivamente mais compreensível, porque quando você faz um loop e fecha sobre vars, o fechamento mantém o último valor da var, mas quando você faz o mesmo sobre deixa, cada fechamento no laço tem seu próprio valor para deixar, um la o exemplo por @ Jerry101 acima
TKoL