let vs var: guerra de mundos ou evolução do JavaScript?
\n\nVocê já escreveu código em JavaScript e se pegou pensando: "Por que essa variável se comporta de forma tão estranha?" Ou, pior ainda, encontrou um bug que desaparece ao substituir var por let? Bem-vindo ao clube. A pergunta "What is the difference between 'let' and 'var'?" no Stack Overflow acumula centenas de milhares de visualizações não por acaso — é uma das armadilhas mais comuns para iniciantes e até mesmo para desenvolvedores experientes.
Hoje não vamos apenas listar as diferenças. Vamos olhar sob o capô: entender como let e var afetam o desempenho do seu código, a otimização em engines modernos (V8, SpiderMonkey) e por que a escolha entre eles é uma questão não apenas de estilo, mas também de eficiência. Prepare-se, vai esquentar.
Resumindo o essencial: escopo e hoisting
\n\nAntes de falar sobre desempenho, vamos relembrar o básico. var e let têm três diferenças principais que mudam tudo.
1. Escopo (Scope)
\n\n- \n
var— tem escopo de função. Se a variável é declarada dentro de uma função, ela é visível em toda a função. Se for fora, ela é global. \nlet— tem escopo de bloco. Ela vive apenas dentro das chaves{}mais próximas (loop, condição, bloco). \n
// Exemplo com var\nif (true) {\n var x = 10;\n}\nconsole.log(x); // 10 — a variável "vazou" do bloco\n\n// Exemplo com let\nif (true) {\n let y = 20;\n}\nconsole.log(y); // ReferenceError: y is not defined\n\n\n2. Hoisting e Zona Morta Temporal (TDZ)
\n\nAmbas as variáveis sofrem hoisting, mas se comportam de forma diferente.
\n\n- \n
var: a declaração é içada para o topo do escopo e inicializada com o valorundefined. Você pode acessar a variável antes da sua declaração (mas receberáundefined). \nlet: a declaração é içada, mas não é inicializada. Até o momento da declaração real, a variável está na "zona morta temporal" (Temporal Dead Zone). Qualquer tentativa de acesso gera umReferenceError. \n
// var — "undefined" seguro\nconsole.log(a); // undefined\nvar a = 5;\n\n// let — erro na TDZ\nconsole.log(b); // ReferenceError: Cannot access 'b' before initialization\nlet b = 10;\n\n\n3. Redeclaração
\n\n- \n
var— pode ser redeclarada quantas vezes quiser no mesmo escopo. Nenhum erro será gerado. \nlet— redeclarar no mesmo escopo gera umSyntaxError. \n
var z = 1;\nvar z = 2; // Ok\n\nlet w = 1;\nlet w = 2; // SyntaxError: Identifier 'w' has already been declared\n\n\nAgora, o principal: desempenho e otimização
\n\nMuitos pensam: "Já que let é o novo padrão, ele é mais lento que var?" Ou o contrário: "let é mais legal, então é mais rápido". A verdade, como sempre, está no meio e depende do contexto.
Como os engines otimizam variáveis
\n\nOs engines JavaScript modernos (V8 no Chrome/Node.js, SpiderMonkey no Firefox) compilam o código para código de máquina usando compiladores JIT. Eles usam heurísticas para otimização.
\n\n- \n
var: devido ao escopo de função e à possibilidade de redeclaração acidental, é mais difícil para o engine fazer suposições sobre o tipo da variável. Ele frequentemente cria objetosVariableObject"pesados", que armazenam variáveis em memória dinâmica. \nlet: o escopo de bloco e a proibição de redeclaração dão ao engine mais