Olá Habr! Apresento a você a tradução do artigo
“var vs let vs const em JavaScript” de Tyler McGinnis.

Neste artigo, você aprenderá duas novas maneiras de criar variáveis em Javascript (ES6), let e const. No decorrer deste artigo, examinaremos as diferenças entre
var ,
let e
const , além de tópicos relacionados, como: “escopo da função versus escopo do bloco”, “aumento” de variáveis e imunidade.
Se você preferir um vídeo, assista a este (original em inglês):
O ES2015 (ou ES6) nos apresentou duas novas maneiras de criar variáveis,
let e
const . Mas antes de nos aprofundarmos nas diferenças entre
var ,
let e
const , existem alguns tópicos que você deve conhecer primeiro. Estas são a declaração de variáveis e sua inicialização, escopo (um escopo especial da função) e “aumento”.
Declarando e inicializando variáveis
Uma declaração de variável introduz um novo identificador.
var declaration
Acima, criamos um novo identificador que denominamos "declaração". Em Javascript, quando criadas, as variáveis são inicializadas com um valor
indefinido . Isso significa que, se tentarmos gerar nossa variável de
declaração , ficaremos
indefinidos .
var declaration console.log(declaration)
E assim, inferimos a variável de
declaração e ficamos
indefinidos .
Comparado a declarar uma variável, inicializar uma variável é a primeira vez que você define o valor dessa variável.
var declaration console.log(declaration)
E assim, aqui inicializamos a variável de
declaração escrevendo uma string para ela.
Isso nos leva ao próximo conceito, escopo.
Âmbito de aplicação
Um escopo descreve onde a variável e as funções podem ser acessadas dentro do nosso programa. Em Javascript, existem 2 tipos de escopos - o escopo global e o escopo de uma função . De acordo com a especificação oficial,
"Se uma declaração de variável ocorrer dentro de uma declaração de função, a variável é definida no escopo local desta função ..."
Isso significa que, se você criar uma variável usando var , o escopo dessa variável será a função em que foi criada e estará disponível apenas dentro dessa função ou em qualquer outra função aninhada.
function getDate () { var date = new Date() return date } getDate() console.log(date)
Acima, tentamos acessar a variável de fora da função na qual ela foi declarada. Como o escopo da variável date é a função getDate , ela está disponível apenas dentro desta função ou em qualquer outra função aninhada em getDate (como mostrado abaixo).
function getDate () { var date = new Date() function formatDate () { return date.toDateString().slice(4)
Agora vamos dar uma olhada em um exemplo mais avançado. Digamos que temos uma matriz de preços e precisamos de uma função que aceite essa matriz, bem como uma variável de desconto , e nos devolva uma nova matriz de preços com descontos. O objetivo final pode ser algo como isto:
discountPrices([100, 200, 300], .5)
E a implementação pode ser algo como isto:
function discountPrices (prices, discount) { var discounted = [] for (var i = 0; i < prices.length; i++) { var discountedPrice = prices[i] * (1 - discount) var finalPrice = Math.round(discountedPrice * 100) / 100 discounted.push(finalPrice) } return discounted }
Parece bastante simples, mas o que isso tem a ver com o escopo do bloco? Dê uma olhada nisso para loop. As variáveis declaradas dentro dele são acessíveis fora dela? Acontece disponível.
function discountPrices (prices, discount) { var discounted = [] for (var i = 0; i < prices.length; i++) { var discountedPrice = prices[i] * (1 - discount) var finalPrice = Math.round(discountedPrice * 100) / 100 discounted.push(finalPrice) } console.log(i)
Se o JavaScript é a única linguagem de programação que você conhece, talvez não precise se preocupar muito com isso. No entanto, se você chegou ao JavaScript de outra linguagem de programação, em particular uma linguagem de programação que bloqueia o escopo, provavelmente está um pouco preocupado com o que está acontecendo aqui.
Não está quebrado, apenas funciona um pouco estranho. Realmente não há razão para ter acesso a i , discountPrice e finalPrice fora do loop for . Não nos faz nenhum bem e pode até nos prejudicar em algumas situações. No entanto, como as variáveis são declaradas usando var , elas se enquadram no escopo da função e você pode acessá-las.
Agora discutimos a declaração e a inicialização de variáveis, bem como o escopo, outra coisa com a qual precisamos lidar antes de mergulhar nas diferenças entre let e const , isso é "aumentar".
"Elevador"
Lembre-se, foi dito anteriormente: "No Javascript, quando criadas, as variáveis são inicializadas com o valor indefinido". Acontece que significa "elevação". O intérprete JavaScript define as variáveis declaradas como indefinidas durante uma fase chamada "Criação".
Para um estudo mais detalhado da fase de criação, "Elevação" e escopos, leia este artigo: "O melhor guia para içamento, escopos e fechamentos em JavaScript" .
Vamos dar uma olhada no exemplo anterior e ver como a “elevação” afeta isso.
function discountPrices (prices, discount) { var discounted = undefined var i = undefined var discountedPrice = undefined var finalPrice = undefined discounted = [] for (var i = 0; i < prices.length; i++) { discountedPrice = prices[i] * (1 - discount) finalPrice = Math.round(discountedPrice * 100) / 100 discounted.push(finalPrice) } console.log(i)
Observe que todas as variáveis declaradas foram definidas como indefinidas . Por isso, se você tentar acessar um deles antes que ele seja realmente anunciado, ficará indefinido .
function discountPrices (prices, discount) { console.log(discounted)
Agora você sabe tudo o que precisa sobre var , agora vamos finalmente falar sobre o principal objetivo para o qual estamos aqui: qual é a diferença entre var , let e const ?
var, let ou const
Para começar, vamos comparar var e let . A principal diferença entre var e let é que, além do escopo global e do escopo da função, é possível definir variáveis no escopo do bloco. Isso significa que a variável criada usando a palavra-chave let está disponível dentro do "bloco" onde foi criada, bem como dentro de blocos aninhados. Quando eu disse "bloquear", quis dizer algo cercado por chaves {}, como um loop for ou uma declaração if .
Então, voltemos à nossa função discountPrices pela última vez.
function discountPrices (prices, discount) { var discounted = [] for (var i = 0; i < prices.length; i++) { var discountedPrice = prices[i] * (1 - discount) var finalPrice = Math.round(discountedPrice * 100) / 100 discounted.push(finalPrice) } console.log(i)
Lembre-se de que temos o direito de gerar i , discountPrice e finalPrice fora do loop for , pois eles foram declarados usando var e as variáveis declaradas usando a palavra-chave var são limitadas pelo escopo da função. Mas o que acontece agora se alterarmos var para permitir e tentar executar nosso código?
function discountPrices (prices, discount) { let discounted = [] for (let i = 0; i < prices.length; i++) { let discountedPrice = prices[i] * (1 - discount) let finalPrice = Math.round(discountedPrice * 100) / 100 discounted.push(finalPrice) } console.log(i)
Temos o ReferenceError: i não está definido . O que nos diz que a variável declarada com let é limitada ao escopo do bloco, não à função. Tente chamar i (ou DiscountPrice ou finalPrice ) fora do "bloco" onde eles foram declarados, e isso nos dará um erro de chamada, como acabamos de ver.
var VS let var: let:
As seguintes diferenças estão relacionadas à “elevação”. Dissemos anteriormente que a definição de "elevação" é: "O interpretador JavaScript define as variáveis declaradas como indefinidas durante a fase chamada" Criação "." Também vimos isso em ação chamando a variável antes que ela fosse declarada (você ficou indefinido ).
function discountPrices (prices, discount) { console.log(discounted)
Não me lembro de um único caso de uso em que você realmente gostaria de acessar uma variável antes de declará-la. Parece que obter um ReferenceError seria melhor do que ficar indefinido .
De fato, é isso que let faz. Se você tentar acessar uma variável antes de sua declaração com let , em vez de ficar indefinido (como era ao declarar com var ), você obterá um ReferenceError .
function discountPrices (prices, discount) { console.log(discounted)
var VS let var: undefined . let: ReferenceError .
deixe ou const
Agora você entende a diferença entre var e let, e a const? Acontece que const é quase o mesmo que let. No entanto, há uma diferença: se você atribuiu um valor usando const, não poderá alterá-lo para outro.
let name = 'Tyler' const handle = 'tylermcginnis' name = 'Tyler McGinnis'
A conclusão do exposto acima é que variáveis declaradas com let podem ser substituídas, e variáveis declaradas com const não podem.
Ótimo, agora que você deseja que sua variável seja imutável, você pode declá-la com const . Ou na verdade não. Só porque uma variável foi declarada usando const não significa que é imutável, tudo o que significa é que não pode ser substituída. Abaixo está um bom exemplo.
const person = { name: 'Kim Kardashian' } person.name = 'Kim Kardashian West'
Observe que alterar a propriedade de um objeto não é uma substituição, portanto, mesmo que o objeto seja declarado usando const , isso não significa que você não pode alterar nenhuma de suas propriedades. Isso significa apenas que você não pode substituir este objeto.
Agora, a pergunta mais importante que ainda não foi respondida: o que devo usar var , let ou const ? A opinião mais popular, e à qual eu aderi, é sempre usar const até que você saiba se a variável será alterada. A razão para isso é que o uso de const deixa claro para você e para os futuros desenvolvedores que devem ler seu código que essa variável não deve ser alterada. Se você precisar alterá-lo (por exemplo, em um loop for ), use let .
Não há muitos casos entre variáveis que mudam e variáveis que não mudam. Isso significa que você nunca precisará usar var novamente.
Agora, a opinião impopular, embora ainda tenha justificativa, é que você nunca deve usar const , embora esteja tentando mostrar que essa variável é imutável, como vimos acima, isso não é totalmente verdade. Os desenvolvedores que mantêm essa opinião sempre usam let , desde que não haja variáveis que sejam realmente constantes, como _LOCATION_ = ....
Vamos fazer um resumo do exposto acima, var é limitado pelo escopo da função e, se você tentar acessar essa variável antes da declaração, ficará indefinido . const e let são limitados pelo escopo do bloco e, se você tentar acessar essas variáveis antes de declará-las, obterá um ReferenceError . E a diferença entre const e let é que o valor que foi atribuído a const não pode ser substituído, ao contrário de let .
var VS let VS const var: undefined . let: ReferenceError . const: ReferenceError .
Este artigo foi publicado originalmente em tylermcginnis.com como parte do curso Modern JavaScript .
Obrigado por ler esta tradução, espero que você tenha encontrado algo novo e útil para si mesmo. Ficarei feliz em ver o feedback!