Variáveis: var, let e const
Nesta aula, exploramos as três formas de declarar variáveis em JavaScript: var, let e const. Abordamos desde a sintaxe básica de declaração e atribuição até os conceitos avançados de escopo, hoisting e boas práticas de uso. Ao final, você será capaz de escolher a declaração mais adequada para cada situação.
Em JavaScript, variáveis são contêineres para armazenar dados. A linguagem oferece três palavras-chave para declarar variáveis: var, let e const. Cada uma possui regras específicas de escopo, hoisting e reatribuição. Compreender essas diferenças é essencial para escrever código limpo, previsível e livre de bugs.
Nesta aula, veremos na prática como cada declaração se comporta, desde a simples atribuição até os mecanismos internos de elevação (hoisting). Ao final, você terá clareza sobre quando usar cada uma.
Declaração e atribuição
A declaração de uma variável cria um identificador no escopo atual. A atribuição armazena um valor nesse identificador. Com var, let e const, a sintaxe é semelhante, mas o comportamento difere.
var permite redeclarar a mesma variável no mesmo escopo, enquanto let e const não. const exige que a variável seja inicializada no momento da declaração e não pode ser reatribuída (embora objetos e arrays possam ter seus conteúdos alterados).
// Declaração e atribuição com var
var nome = 'Maria';
var nome = 'João'; // permitido (redeclaração)
console.log(nome); // 'João'
// Com let
let idade = 25;
// let idade = 30; // Erro: Identificador 'idade' já declarado
idade = 30; // permitido (reatribuição)
console.log(idade); // 30
// Com const
const PI = 3.14159;
// PI = 3; // Erro: Atribuição a variável constante.
// const cor; // Erro: falta inicializador
console.log(PI); // 3.14159Note que const não impede a mutação de objetos. O vínculo é constante, não o valor.
Escopo de função vs bloco
Escopo define onde a variável é acessível. var tem escopo de função (ou global, se declarada fora de função). Já let e const têm escopo de bloco (delimitado por {}).
Isso significa que var vaza para fora de blocos como if ou for, enquanto let e const ficam restritas ao bloco. Exemplo:
function exemploEscopo() {
if (true) {
var a = 1; // escopo da função
let b = 2; // escopo do bloco if
const c = 3; // escopo do bloco if
}
console.log(a); // 1 (acessível)
// console.log(b); // Erro: b não está definida
// console.log(c); // Erro: c não está definida
}
exemploEscopo();Em loops for, a diferença é crucial. Com var, a variável do contador vaza para fora do loop; com let, ela fica confinada ao bloco do for.
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // imprime 3, 3, 3
}
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 100); // imprime 0, 1, 2
}Isso ocorre porque var usa o mesmo i para todas as iterações, enquanto let cria uma nova variável a cada iteração.
Hoisting
Hoisting é o comportamento de elevar declarações para o topo do escopo antes da execução. Em JavaScript, as declarações com var são içadas (hoisted) e inicializadas com undefined. Já let e const também são içadas, mas não são inicializadas, ficando em uma "zona morta temporal" (temporal dead zone) até a declaração.
Exemplo com var:
console.log(x); // undefined (não dá erro)
var x = 5;
console.log(x); // 5Com let ou const:
// console.log(y); // Erro: Cannot access 'y' before initialization
let y = 10;
console.log(y); // 10
// console.log(z); // Erro: Cannot access 'z' before initialization
const z = 20;
console.log(z); // 20Na prática, o JavaScript move a declaração (var y) para o topo, mas a inicialização permanece no lugar. Para let e const, a declaração é içada, mas a variável não pode ser acessada antes da linha onde é declarada.
Quando usar cada uma
Atualmente, var é considerada obsoleta para novos projetos. Prefira const sempre que o valor não precisar ser reatribuído (a maioria dos casos). Use let quando precisar reatribuir (contadores, acumuladores). Evite var a menos que esteja mantendo código legado ou precise de compatibilidade com ambientes muito antigos.
Boas práticas:
- Use
constpor padrão. - Use
letapenas quando for reatribuir. - Nunca use
varem código novo. - Declare variáveis no topo do escopo (bloco) para evitar confusão com hoisting.
Exemplo prático:
// Preferido
const nome = 'Ana';
let contador = 0;
contador++;
// Evitado
var nome2 = 'João';Referências
Exercícios
- Qual a diferença de escopo entre
varelet? Dê um exemplo. - O que acontece se tentarmos acessar uma variável
letantes de sua declaração? E comvar? - Corrija o código abaixo para que imprima 0, 1, 2 usando
letouconstno lugar devar: - É possível redeclarar uma variável
constno mesmo escopo? E reatribuir? - Escreva um exemplo que demonstre a zona morta temporal (temporal dead zone) com
let.
var tem escopo de função (ou global), enquanto let tem escopo de bloco. Exemplo: dentro de um if, var vaza para fora, let não.let ou const, ocorre um erro de referência (ReferenceError) devido à zona morta temporal. Com var, retorna undefined (hoisting).for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}var i por let i:for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}const. Ela deve ser inicializada na declaração e seu vínculo é imutável.console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x = 10;