Entendendo a diferença entre variáveis em JavaScript: let, const e var
Ao trabalhar com JavaScript no dia a dia, você provavelmente já se deparou com situações em que uma variável assumia o valor errado ou simplesmente não funcionava como o esperado. A confusão entre os três tipos de declaração de variáveis é um dos problemas mais comuns que vejo em códigos de iniciantes e até de desenvolvedores intermediários. Vou explicar de forma direta como cada uma funciona e onde elas realmente se diferenciam na prática. A principal diferença entre var, let e const está no escopo e no comportamento de reatribuição. O var usa escopo de função, o que significa que se você declarar uma variável dentro de um bloco if ou for, ela vai "vazar" para fora desse bloco. Já o let e o const usam escopo de bloco, o que oferece um controle muito mais previsível sobre onde uma variável pode ser acessada.
qual a principal diferença entre var, let e const em JavaScript
O var foi o primeiro tipo de declaração disponível no JavaScript e continua sendo aceito por questões de compatibilidade com código legado. Ele sofre de um comportamento chamado hoisting, onde a variável é movida para o topo do escopo durante a compilação. Isso significa que você pode acessar uma variável antes dela ter sido declarada no código, e o JavaScript vai retornar undefined ao invés de dar erro. Essa é uma armadilha clássica que causa bugs difíceis de rastrear. O let resolve o problema do escopo de bloco mas ainda permite reatribuição. Você pode declarar uma variável com let e depois mudar seu valor quantas vezes quiser dentro do mesmo bloco. Isso é útil para contadores de loop, flags de controle e qualquer situação onde o valor precisa variar durante a execução do programa. O let também não sofre do mesmo problema de hoisting que o var tem — ele existe na "temporal dead zone" até que a declaração seja alcançada durante a execução.
O const é literalmente a forma mais restrita de declaração. Ele exige que você atribua um valor no momento da declaração e não permite reatribuição posterior. Se você tentar fazer const x = 5; x = 10;, o JavaScript vai levantar um erro. Isso parece limitante mas na verdade é uma vantagem porque força você a pensar melhor sobre quando um valor precisa ser mutável. Dados que não mudam devem usar const. Variáveis que precisam mudar devem usar let. Variáveis declaradas com var devem basically sumir do seu vocabulário. Um ponto importante que muita gente perde de vista é que const não cria imutabilidade real. Se você declarar const obj = { nome: "teste" } e depois fizer obj.nome = "novo", isso funciona perfeitamente porque o const protege apenas a referência, não o conteúdo do objeto. Para criar imutabilidade de verdade, você precisaria usar Object.freeze() ou bibliotecas como Immutable.js. Eu perdi horas debugando um problema assim num projeto real onde uma constante parecia estar sendo modificada por uma função externa, só que na verdade era o conteúdo interno que estava mudando.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Quando usar cada tipo na prática
Na minha experiência, a regra prática é simples: use const para tudo que não precisa mudar. Use let apenas quando você tem certeza de que o valor vai precisar ser reatribuído. E esqueça var completamente, a menos que esteja mantendo código antigo que depende dele. Em projetos novos, eu recomendo configurar o ESLint com a regra no-var para impedir o uso acidental de var. Outra situação prática é o uso de let em loops for. Quando você precisa de um contador que varia, let é a escolha natural. Tentar usar const nesse caso só vai te dar erro de reatribuição. Por outro lado, se você tem um loop onde o valor do iterador não precisa ser modificado, const pode funcionar, mas em geral let é mais comum nesse contexto.
O comportamento de hoisting também afeta diferentes tipos de declaration. Funções declaradas com function declaration são completamente hoisted, o que significa que você pode chamá-las antes da declaração no código. Funções arrow e variáveis declaradas com let e const são parcialmente hoisted — elas existem no topo do escopo mas ficam na temporal dead zone até a declaração ser executada. Esse comportamento misturado causa erros do tipo "Cannot access before initialization" que são particularmente frustrantes.
Pegadinhas comuns que acontecem no dia a dia
Uma pegadinha frequente envolve o uso de let dentro de callbacks assíncronos. Se você declarar uma variável com let antes de uma operação assíncrona e depois tentar usá-la dentro de um callback, o valor pode não ser o que você espera dependendo do timing. Isso acontece porque o callback executa depois que o loop ou a sequência de execução já avançou. O workaround mais comum é usar uma função factory ou capturar o valor em uma closure. Outro erro comum é tentar redeclarar variáveis no mesmo escopo. Com var, redeclaração é permitida. Com let e const, isso gera um SyntaxError. Em projetos grandes, essa diferença pode causar problemas quando código de múltiplos desenvolvedores é integrado sem coordenação adequada sobre o escopo das variáveis.
Para quem está começando, o conselho mais prático é: escreva código usando apenas const e let, configure o ESLint, e quando algo não funcionar como esperado, verifique primeiro se não há conflito de escopo ouhoisting. A maioria dos problemas com variáveis em JavaScript se resume a esses dois conceitos básicos mal compreendidos. O ecossistema JavaScript evoluiu significativamente com a introdução do let e const no ES6, e projetos modernos praticamente não usam var mais. Ferramentas como Babel podem transpilar código com let e const para versões mais antigas se você precisar suportar navegadores desatualizados, mas isso é cada vez menos necessário no cenário atual de desenvolvimento web.