Já passou horas procurando um bug e no final era só uma variável vazando do escopo? Bom, pra ser sincero, eu nunca, mas vamos entender porque isso acontece
O que são variáveis?
Variáveis são "caixas" que armazenam valores no Javascript, e podem armazenar qualquer coisa, desde um simples número, a um objeto extenso.
var, let e const
Existem 3 tipos de variáveis no Javascript, são elas: var, const e let. No que se diferenciam? Os tipos var e let permitem que você re-atribua um valor para ela, ou seja, substituir o valor que estava dentro daquela "caixa" por outro. Essa troca não precisa ser para o mesmo tipo anteriormente armazenado, você pode trocar de uma string por um número sem problemas.
const é uma variável que não permite re-atribuição, uma vez colocado um valor nela, não é possível alterar. Vale adiantar que, objetos e arrays declarados como const, podem ter seu conteúdo interno alterado (como alterar uma propriedade do objeto, adicionar mais um item no array), mas você não pode atribuir um outro objeto ou um outro array para essa variável existente.
var vs let: qual usar?
Se var e let são "iguais", qual usar? A resposta é: let. O var abre um espaço para bugs difíceis de rastrear a medida que sua codebase cresce, mas porque isso acontece?
O problema do escopo de função
var é uma variável antiga, deve ser evitada, ainda se encontra em sistemas legados e é mantida por compatibilidade, porém, o problema dela em relação ao let, é que ela existe em escopo de função. Isso significa que, se você declara um var dentro de um if, ela vai existir fora dele também. Já, se você declara um let no exato mesmo lugar, ela deixa de existir* quando o bloco fecha.
if (true) {
var x = "existe fora";
let y = "não existe fora";
}
console.log(x); // "existe fora"
console.log(y); // ReferenceError: y is not defined
Podemos dizer então que var existe e pode ser acessada fora do escopo onde ela foi declarada, enquanto let e const existem em escopo de blocos { }. E isso é que causa bugs difíceis de rastrear, uma variável vivendo em um lugar que você não esperava.
*"deixa de existir" significa que tentar acessar
yfora do bloco lança um erro, diferente dovarque simplesmente retornaundefinedExiste cenários que você conseguesse acessar umconstouletfora do escopo, mas veremos mais sobre isso em Hoisting.