CLEAR — Martin Kenny (CC BY-NC-SA 2.0)

Seja explícito!

Aumente a legibilidade do seu javascript com const e let.

Uma das novidades da versão ES6 do javascript (ou ES2015 — pra você que torceu o nariz) foi a inserção do let e const no reinado solitário do var na declaração de variáveis. Apesar de não ser algo recente, muitos desenvolvedores ainda utilizam o velho conhecido por inúmeras razões. Mas existem algumas boas justificativas para que o uso do var fique apenas no passado.

var e hoisting

Quando usamos var em javascript, o escopo da variável é a função onde a mesma foi declarada (ou global, caso não tenha sido declarada dentro de nenhuma função). Isso permite que algumas coisas, não tão comum em outras linguagens, funcionem. Por exemplo:

Escopo da variável quando declarada com var

Se por um lado isso pode ser visto como flexibilidade, por outro, isso pode ser fonte para problemas de legibilidade no código e até facilitar o aparecimento de bugs. Uma variável que é declarada em algum ponto do código pode estar visível em outra parte do código onde ela não é necessária. Como consequência, acidentalmente um desenvolvedor pode reutilizar essas variáveis e gerar efeitos inesperados. Além disso, imagine quão complicado seria identificar em que parte da função uma variável está sendo utilizada ou alterada — não vou nem falar no caso de ser uma variável global!

Uma variável deve ter um único propósito e seu escopo deve ser o menor possível.

E não só isso, é possível referenciar uma variável antes dela ser declarada! Mas como isso pode ser possível? Calma. Na verdade, o que acontece por baixo dos panos é que todas as declarações são processadas antes de qualquer código ser executado. Na prática é como se todas as declarações fossem movidas para o topo da função. Este comportamento é popularmente conhecido como hoisting.

Hoisting e declarações com var

Por muito tempo recomendou-se declarar variáveis sempre no topo da função. Felizmente, isso não é mais necessário desde o ES6 com a chegada do let e const.

let

Diferentemente do var, o uso do let permite que você declare variáveis com acesso apenas ao bloco, instrução ou expressão em que foram declaradas, ou seja, possui o mais conhecido escopo de bloco (block escope).

let e escopo de bloco

Apesar de não ser possível acessar a variável fora do escopo em que foi declarada, isso não quer dizer que não existe hoisting com o let. Existe. A diferença é que as variáveis não são inicializadas com undefined, como acontece com o var. Deste modo, qualquer tentativa de acesso a uma variável antes da sua declaração irá gerar um erro de referência. Este período entre o início do escopo e a execução da declaração da variável é conhecido como temporal dead zone, ou TDZ.

Temporal Dead Zone

const

O const obedece as mesmas regras de escopo e TDZ do let mas com duas pequenas diferenças: você precisa a inicializar a variável no momento da declaração e você não pode reatribuir valores a ela — daí vem o nome “const” em que o objetivo é declarar valores constantes.

Escopo e TDZ em declarações com const

Mas cuidado! Sua variável pode ser constante mas o objeto que ela referencia não é imutável! É exatamente isso. Não poder reatribuir somente garante que a variável irá referenciar sempre o mesmo objeto, mas o objeto em si continua sendo mutável. Por exemplo, uma constante inicializada com um lista não poderá mais referenciar um outro valor, mas a lista qual ela referencia pode ter suas propriedades alteradas, como adicionar ou remover itens.

Declarações com const vs imutabilidade

Caso você realmente precise de um objeto imutável você tem algumas outras opções como o Object.freeze(), immutable.js, mori.

let vs const

O propósito de uma variável deve sempre estar explícito, e por isso, devemos evitar reusar a mesma variável a menos que isto seja essencial. Deste modo, é preferível utilizar const ao invés de let já que ele nos impõe este comportamento.

A verdade é que na ampla maioria dos casos não precisamos reutilizar variáveis. Somos tentados a fazer por facilidade. Quando você achar que precisa utilizar um let, desafie você mesmo e refatore. E verá que você realmente não precisava — não acredita? dê uma olhada nos exemplos do artigo abaixo.

É claro que existem casos em que a presença de um let é indiscutível, como o uso de contadores e acumuladores em loops, flags em algoritmos matemáticos, etc. Mas de maneira geral, recomenda-se:

  • Sempre use const;
  • Raramente use let (quando estritamente necessário);
  • Nunca use var;

E se você está achando que vai ser difícil lembrar ou se disciplinar a isto, eu tenho uma ótima notícia: linters! (eslint, tslint, jshint, jslint, etc). Eles irão lembrar por você e garantir que você não cometa nenhuma atrocidade com a legibilidade. Os leitores do seu código irão te agradecer por isso — incluindo você.