DEV Community

ane
ane

Posted on • Edited on

JavaScripting #1: como utilizar as declarações var, let e const?

No início dos meus estudos mais aprofundados em JavaScript, na disciplina de Desenvolvimento Web I, discernir entre os tipos de declarações de variáveis era, certamente, uma das minhas maiores dificuldades. Afinal de contas – e era assim mesmo que eu pensava –, não é tudo a mesma coisa?

Adivinha só: não é! E muito disso se baseia nos conceitos de escopo. Se em tempos remotos só tínhamos o var como declaração de variáveis em escopos globais e de função, com a chegada do ECMAScript 6, lá em 2015, tornou-se possível declarar variáveis com let e const e também surgiram os escopos de bloco, funcionalidades que deixaram o JavaScript mais uniforme e (um pouco) menos sujeito a problemas de segurança.

🚨 ...e acho que aqui vale um pequeno adendo sobre o que é um escopo e quais os tipos de escopos que existem:

O escopo global se refere a todo o código – ou seja, se você tiver 20 funções diferentes no seu documento de código e declarar uma variável global, é possível utilizar essa variável nessas 20 funções. Assim:

var hello = "Bem-vindo!";

function visitorOne() {
  alert(hello);
}

function visitorTwo() {
  alert(hello);
}

function visitorThree() {
  alert(hello);
}

alert(hello);
Enter fullscreen mode Exit fullscreen mode

Já o escopo local (ou de função) é todo pedaço de código referente a uma função. Ou seja, uma variável de função é toda variável declarada dentro de uma função e que só pode ser acessada dentro dela. Um exemplo:

function showComments() {
  let comment = "Muito legal!";
  console.log(comment);
  //Ao acessar essa função, o valor da variável "comment" será mostrado em tela.
}

showComments();
//Muito legal!

function showOtherComments() {
  console.log(comment);
  //Aqui o resultado retornado pela função hideComments será um erro dizendo que a variável não foi definida, pois é impossível acessar a variável "comment", já que é uma variável reservada APENAS ao escopo da função showComments(), logo, será interpretada como se fosse uma variável inexistente.
}

showOtherComments();
//ReferenceError: comment is not defined
Enter fullscreen mode Exit fullscreen mode

Por fim, o escopo de bloco é qualquer região do código que utilize os famosos "bigodinhos" (ou melhor, chaves), assim como as funções, porém, a diferença esse tipo de escopo é criado por estruturas de controle, tais como as estruturas condicionais if/else ou switch, de repetição for ou do/while, entre outros. Por ter essa particularidade, as variáveis declaradas em escopo de bloco podem ser acessadas dentro de toda a função, e não apenas na estrutura de controle. Tipo isso aqui:

function commentPost() {
  //Escopo de função
  let blogPost = "finished";

  if (blogPost === "finished") {
    //Escopo de bloco
    var username = "anewrites";
    alert(`Comenta aí, ${username}! :P`);
  } else {
    alert("Continue lendo <3");
  }

  console.log(blogPost); //finished
  console.log(username); //anewrites
}
Enter fullscreen mode Exit fullscreen mode

Agora que já temos uma pequena noção de como cada tipo de escopo funciona, vamos dar uma olhada no que significa cada declaração de variável e como elas podem ser utilizadas dentro de cada tipo de escopo. 👇

O velho conhecido "var"

Como eu comentei ali no comecinho do post, o var era a única declaração de variável global e de escopo de função disponível até a chegada do ES6 – ou seja, o var pode ser declarado globalmente e ser acessado em qualquer região do código, ou ser declarado em escopos de função e acessado apenas nas funções as quais essas variáveis pertencem. Resumidamente, a vantagem de utilizar var, pelo menos até a chegada do ES6, é diferenciar variável local de variável global.

//Sintaxe:
var varname1 = value1;

//Var declarada de forma global

var posts = 2;

function postCounter() {
  console.log(posts);
}

function postCounter2() {
  console.log(posts);
}

function postCounter3() {
  console.log(posts);
}

postCounter(); //2
postCounter(); //2
postCounter(); //2
console.log(posts); //2

//Var declarada em escopo de função

var name = "Ane";

function postCounter() {
  var numberOfPosts = 2;
  console.log(`${name} fez ${numberOfPosts} posts até agora!`);
}
postCounter(); //Ane fez 2 posts até agora!
console.log(numberOfPosts); //ReferenceError: numberOfPosts is not defined (ao tentar acessar essa variável fora da função, obtemos um erro, pois ela só "existe" dentro da função em que foi declarada)
Enter fullscreen mode Exit fullscreen mode

Além dessas duas maneiras de declarar uma var, é possível atribuir outro valor à mesma variável. Desta forma:

var posts = 1;
var posts = 2;
console.log(posts); //2
Enter fullscreen mode Exit fullscreen mode

E o hoisting, hein? 🏗️

Eu até falei que é possível atribuir outro valor a uma variável var, mas tem algo um tanto complicado sobre fazer isso: o hoisting. Derivado do termo hoist em inglês, que significa "levantar" ou "içar" algo, o hoisting faz com que uma var seja posicionada no início do contexto de execução no qual ela foi declarada – ou seja, esse mecanismo faz com que as variáveis var que você declarou "subam" para o início do seu trecho de código antes mesmo que ele seja executado, algo que faz com que a sua variável, que antes tinha um valor, seja interpretada como undefined, mais ou menos assim:

var texto = "dá pra evitar hoisting? D:";
//Variável var global

function writeOnScreen() {
  console.log(texto);
  var texto = "às vezes é inevitável...";
  console.log(texto);
}

writeOnScreen();
//undefined
//às vezes é inevitável...
Enter fullscreen mode Exit fullscreen mode

Mas ué, cadé o primeiro console.log?

Então, esse é o conceito do hoisting. Ao invés de interpretar a variável global e exibi-la em tela, esse mecanismo irá inicializar a variável global lá no início do bloco de função, e só depois é que ela será executada. Pra entender de vez como isso funciona, vamos pensar de acordo com o próprio JavaScript, passo a passo. É assim que esse bloco de função foi executado:

var texto = "dá pra evitar hoisting? D:";
//Variável var global

function writeOnScreen() {
  var texto; //A variável global foi "levantada" durante a execução até o início deste bloco de função
  console.log(texto); //undefined (pois ela só foi declarada aqui dentro, mas não foi definida)
  var texto = "às vezes é inevitável..."; //Valor atribuído pela primeira vez (de acordo com o hoisting) dentro deste bloco de função
  console.log(texto);
}

writeOnScreen();
//undefined
//às vezes é inevitável...
Enter fullscreen mode Exit fullscreen mode

Aqui notamos uma das desvantagens de utilizar declarações var. Caso ela sofra hoisting, será inicializada sempre com um valor undefined. E claro, talvez a maior brecha de segurança da utilização do var seja a facilidade em redefinir valores para uma declaração var, independente do seu escopo de origem, prática que pode vir a causar inúmeros bugs na sua aplicação. Portanto – e essa é uma opinião minha, baseada no que estudei até aqui e ouvi de pessoas desenvolvedoras mais experientes -, com a chegada do ECMAScript 6, é possível evitar a utilização do var, a não ser que a aplicação em questão seja utilizada em navegadores mais antigos, que não possuam suporte a let e const.

A chegada do let

O ECMAScript 6 trouxe diversas novidades, e uma delas foi a chegada da declaração let, uma versão mais consistente de declaração de variáveis e que evita problemas de declaração repetida no mesmo escopo, por exemplo. A seguir, vamos ver algumas das funcionalidades do let e como elas podem ser vantajosas para o nosso código:

  • O let é declarado apenas em escopos de bloco, ou seja, qualquer pedaço do código delimitado por chaves ({}) e a variável em questão estará disponível apenas neste escopo, dessa forma:
let age = "25";

if (age > 20) {
  let name = "fulano";
  console.log(name); //fulano
}
console.log(name); //name is not defined
Enter fullscreen mode Exit fullscreen mode
  • O let também não permite uma declaração repetida de uma variável como é visto no var. É possível atribuir outro valor a uma variável let, mas não é permitido declará-la novamente. Por exemplo:
//Atribuição de um novo valor
let bolo = "morango";
bolo = "abacaxi";

console.log(bolo); //abacaxi

//Declaração repetida da variável
let bolo = "morango";
let bolo = "abacaxi"; //Identificador 'bolo' já foi declarado
Enter fullscreen mode Exit fullscreen mode

Porém, isso é uma regra apenas para declarações de variáveis no mesmo escopo. Em escopos diferentes, essa declaração repetida funcionará normalmente, já que o JavaScript interpreta variáveis de escopos diferentes como declarações diferentes.

Acredito que o let seja um tanto mais seguro que o var nesse sentido. Ao declarar duas variáveis com o mesmo nome, mas em escopos diferentes, por exemplo, não temos o risco de estarmos mexendo na mesma variável, como ocorre em variáveis do tipo var.

Por fim, a variável constante!

É assim que eu gosto de chamar a declaração const, pra ser sincera. E, de fato, é mais ou menos isso. O const armazena valores read-only que não podem ser alterados, ou seja, que se mantêm constantes. Algumas características do const:

  • Variáveis declaradas como const, assim como let, só podem ser acessadas em escopo de bloco;

  • Meio óbvio, mas é bom reforçar: variáveis const não podem ser redefinidas. Ou seja, você não poderá fazer isso:

const suco = "laranja";
suco = "limão"; //TypeError: Atribuição à variável constante.

//E nem isso:

const torta = "limão";
const torta = "banofee"; //Identificador 'torta' já foi declarado
Enter fullscreen mode Exit fullscreen mode
  • Justamente por ser uma variável constante ( 🤪 ), o const precisa ser inicializado com um valor atribuído. Caso contrário, o seguinte erro será mostrado:
const fruta;
 //Missing initializer in const declaration
Enter fullscreen mode Exit fullscreen mode

Certo, mas então qual delas eu devo usar?

Isso vai depender muito de qual aplicação você está desenvolvendo, e para qual browser. Se o seu projeto for direcionado a browsers mais antigos, continue utilizando var sem problemas, pois não é garantido que browsers mais antigos forneçam suporte ao ECMAScript 6. Do contrário, se estamos falando de variáveis que vão ser alteradas, acredito no let como a melhor forma de declarar variáveis mutáveis, ou pelo menos a mais segura e descomplicada. Já para variáveis read-only, o const é a declaração que fornece maior segurança. :)

Isso é um pouquinho do que sei sobre declaração de variáveis no JavaScript como iniciante no assunto 😉 Caso tenham gostado ou queiram me enviar sugestões, dúvidas ou críticas, fiquem à vontade para comentar esse post ou me chamar lá no twitter @anestudies ;) Até breve!

Referências

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Grammar_and_types
https://developer.mozilla.org/pt-BR/docs/Glossary/Scope
https://www.alura.com.br/artigos/entenda-diferenca-entre-var-let-e-const-no-javascript
https://walde.co/2016/02/15/javascript-hoisting-o-que-e/

Top comments (0)