Entendendo as variáveis no Javascript

As variáveis no JavaScript permitem armazenar dados em pequenos espaços da memória e reutilizar esses valores ao longo de toda a aplicação. Por isso, entender como declarar, atribuir e nomear cada variável é um dos primeiros passos de quem começa a programar para a Web.

Com elas, você guarda números, textos, valores lógicos e até estruturas mais complexas, como objetos e listas. Neste artigo, vamos percorrer todo o básico para usar variáveis de forma correta dentro do JavaScript, desde a escolha da palavra reservada até as boas práticas de nomenclatura.

O que são variáveis no JavaScript

Uma variável é um nome que aponta para um valor guardado na memória. Em outras palavras, ela funciona como uma etiqueta que você usa para encontrar e manipular um dado sempre que precisar.

Na prática, as variáveis no JavaScript não exigem que você informe o tipo do dado no momento da declaração. Afinal, o JavaScript é uma linguagem de tipagem dinâmica, então o tipo acompanha o valor, e não a variável.

Dessa forma, a mesma variável pode receber um número agora e um texto depois. Embora isso traga flexibilidade, também exige atenção redobrada, porque uma troca acidental de tipo costuma gerar erros difíceis de rastrear.

Curso gratuito de JavaScript

Quer aprender mais sobre uma das linguagens mais usadas da Web de forma simples, direta e totalmente gratuita? Então conheça o curso gratuito de Fundamentos do JavaScript do balta.io, que aprofunda os temas deste artigo com exemplos práticos.

Além disso, se você ainda está dando os primeiros passos, vale ler antes o que é JavaScript para entender onde a linguagem roda e por que ela é tão importante.

Quais são os tipos de declaração de variáveis no JavaScript

Como vimos, uma variável reserva um pequeno espaço na memória onde podemos salvar números, textos ou qualquer outro tipo de dado. Pensando nisso, o JavaScript oferece três formas diferentes de declarar variáveis: var, let e const.

À primeira vista, elas parecem similares. No entanto, cada uma tem um comportamento próprio em relação a escopo, redeclaração e reatribuição.

Por esse motivo, conhecer as diferenças entre as declarações de variáveis no JavaScript evita boa parte dos bugs mais comuns de iniciantes.

A palavra reservada var

A palavra var é a forma mais antiga de declarar variáveis no JavaScript. Ela tem escopo de função, ou seja, a variável fica visível em toda a função onde foi declarada, mesmo fora do bloco de chaves em que apareceu.

Quando declarada fora de qualquer função, a variável criada com var vira global. Nesse caso, segundo a documentação da MDN sobre var, ela também passa a ser uma propriedade do objeto global (globalThis).

Por isso, o var foi muito usado quando precisávamos acessar um valor em diferentes partes da aplicação, como uma configuração que não muda. Claro, devemos analisar todo o contexto, pois nem todo tipo de informação pode ficar pública para a aplicação inteira.

var appName = "Store";

function showAppName() {
    // appName é global, então está visível aqui
    console.log(appName);
}

if (true) {
    var message = "Hello";
}

// var ignora o bloco do if
console.log(message); // "Hello"

Além disso, o var permite redeclarar a mesma variável sem erro e sofre hoisting. Com isso, a declaração sobe para o topo da função e a variável existe com o valor undefined antes da linha em que você a escreveu.

console.log(total); // undefined, não gera erro
var total = 10;

Esse comportamento confunde muita gente. Por essa razão, a própria MDN recomenda preferir let e const no código moderno.

A palavra reservada let

O let é um recurso muito mais moderno para declarar variáveis no JavaScript, introduzido no ECMAScript 2015. Ele tem escopo de bloco (block-scoped), ou seja, sua visibilidade fica limitada ao bloco de código em que foi definido.

Um bloco de código é delimitado pelas chaves { }, como o corpo de uma função, de um if ou de um for. Sempre que precisamos armazenar algo que só será usado dentro desse trecho, o let é a opção recomendada.

Vale lembrar que, como estamos falando de escopo de bloco, o let não é acessível fora dele. Eu diria que ele funciona como um private, visível somente dentro do bloco que o originou.

let counter = 0;

if (counter === 0) {
    let counter = 5; // outra variável, válida só neste bloco
    console.log(counter); // 5
}

console.log(counter); // 0

for (let i = 0; i < 3; i++) {
    console.log(i);
}
// console.log(i); // ReferenceError: i is not defined

Além disso, o let não permite redeclarar a mesma variável no mesmo bloco. Também existe a chamada zona morta temporal: se você tentar ler a variável antes da linha de declaração, o motor lança um ReferenceError, em vez de devolver undefined.

A palavra reservada const

O uso do const é muito parecido com o do let, pois ele também tem escopo de bloco. A diferença notável é que, depois de declarar um const, você não consegue atribuir um novo valor a ele.

Const vem de constante, então o valor atribuído permanece o mesmo até o fim da vida útil da variável. Por isso, o const exige um valor já na declaração, e escrever const value; gera um erro de sintaxe.

Esse tipo é perfeito quando você não quer correr o risco de trocar um valor por acidente, porque a variável é importante para a lógica da aplicação. Na prática, muitos guias de estilo sugerem usar const por padrão e recorrer ao let apenas quando a reatribuição for necessária.

Exemplo de código com variáveis no JavaScript declaradas com const, mostrando o erro ao tentar atribuir um novo valor a uma constante
Tentar reatribuir uma constante gera erro em tempo de execução.

Há um detalhe importante aqui. O const impede a reatribuição da variável, mas não congela o conteúdo de objetos e arrays, como explica a referência de const na MDN.

const settings = { theme: "dark" };
settings.theme = "light"; // permitido: alteramos uma propriedade
// settings = {};         // TypeError: reatribuição não é permitida

const items = [];
items.push("book"); // permitido: alteramos o conteúdo do array

Diferenças entre var, let e const nas variáveis no JavaScript

Depois de ver cada palavra reservada, vale comparar tudo lado a lado. Assim, fica mais fácil escolher a declaração certa para cada situação.

Característica var let const
Escopo Função Bloco Bloco
Redeclaração no mesmo escopo Permitida Não permitida Não permitida
Reatribuição Permitida Permitida Não permitida
Acesso antes da declaração Retorna undefined ReferenceError ReferenceError
Valor inicial obrigatório Não Não Sim

Em resumo, o var faz sentido principalmente em código legado. Já em projetos novos, as variáveis no JavaScript costumam ser declaradas com const e, quando o valor precisa mudar, com let.

Como atribuir valores às variáveis no JavaScript

As variáveis podem armazenar diferentes tipos de valores, sejam textos, números, booleanos ou estruturas mais complexas, como objetos. Então, vamos analisar como atribuir cada tipo de dado a uma variável.

// atribuindo números
let age = 25;

// atribuindo texto
let name = "Pedro";

// atribuindo booleanos
let isStudying = true;

// atribuindo objetos
let person = { name: "João", age: 26 };

Cada exemplo acima mostra como atribuir um tipo diferente de dado. Repare que, nas variáveis no JavaScript, não é necessário dizer qual será o tipo.

No momento da atribuição, o JavaScript identifica automaticamente o tipo do valor recebido. Você pode confirmar isso com o operador typeof, que devolve uma string com o nome do tipo.

console.log(typeof age);       // "number"
console.log(typeof name);      // "string"
console.log(typeof isStudying); // "boolean"
console.log(typeof person);    // "object"

Além desses, a linguagem também tem os tipos primitivos undefined, null, bigint e symbol. Uma variável declarada com let sem valor inicial, por exemplo, começa com undefined.

Atribuindo por valor e por referência

Quando atribuímos valores primitivos, como números, a variável guarda o próprio valor. Isso é o que costumamos chamar de cópia por valor.

Por isso, se você atribuir o valor de uma variável a outra, terá duas cópias independentes. Alterar uma delas não afeta a outra.

let firstNumber = 7;

// cópia por valor: cria uma cópia independente
let secondNumber = firstNumber;

secondNumber = 10;
console.log(firstNumber); // 7

Porém, quando lidamos com tipos complexos, como arrays e objetos, a variável guarda uma referência para o endereço desses dados na memória. Em outras palavras, em vez de uma cópia exata, a nova variável recebe apenas a referência para a mesma estrutura.

let firstList = [7, 8, 9];

// cópia por referência: as duas variáveis apontam para o mesmo array
let secondList = firstList;

secondList.push(10);
console.log(firstList); // [7, 8, 9, 10]

Esse comportamento explica por que alterar secondList também muda firstList. Se você precisar de uma cópia independente, pode usar o operador spread, como em [...firstList], que cria um novo array raso.

É importante saber que existem esses dois tipos de atribuição e que a memória funciona de forma diferente em cada um. Muitas vezes, quando enfrentamos um problema estranho com variáveis no JavaScript, entender a diferença entre valor e referência resolve a dúvida.

Para se aprofundar nesse assunto, confira também o guia básico sobre arrays no JavaScript, que mostra como manipular listas na prática.

Escopo das variáveis no JavaScript na prática

O escopo define em quais partes do código uma variável pode ser lida ou alterada. Na prática, ele é o principal motivo para preferir let e const em vez de var.

Veja um exemplo clássico com laço de repetição e funções assíncronas. Com var, todas as funções agendadas compartilham a mesma variável, enquanto com let cada volta do laço recebe uma variável nova.

for (var i = 0; i < 3; i++) {
    setTimeout(() => console.log("var:", i), 0);
}
// imprime var: 3 três vezes

for (let j = 0; j < 3; j++) {
    setTimeout(() => console.log("let:", j), 0);
}
// imprime let: 0, let: 1 e let: 2

Esse detalhe parece pequeno, mas causa bugs reais em aplicações. Portanto, limitar o escopo das variáveis no JavaScript ao menor bloco possível deixa o código mais previsível.

Além disso, evite criar variáveis sem nenhuma palavra reservada, como total = 10. Fora do modo estrito, isso cria uma variável global implícita, enquanto no modo estrito ("use strict") o motor lança um erro.

Melhores práticas para nomes de variáveis no JavaScript

Um ponto muito importante é a escolha dos nomes. Afinal, um bom nome explica o que a variável guarda sem que o leitor precise procurar a atribuição.

Antes das boas práticas, vale conhecer as regras da linguagem. Um nome pode conter letras, dígitos, $ e _, mas não pode começar com dígito, e o JavaScript diferencia maiúsculas de minúsculas, então total e Total são variáveis diferentes.

Agora, vamos explorar algumas boas práticas que deixam suas variáveis no JavaScript mais claras.

1. Escolha nomes significativos

O nome de uma variável deve explicar brevemente o seu propósito. Em vez de nomes genéricos, como x ou data, prefira um nome que faça sentido no contexto.

Por exemplo, se precisamos guardar o valor total de um produto, um bom nome seria productTotalPrice. Logo de cara, ele mostra qual é a finalidade da variável.

// pouco claro
let v = 150;

// claro
let productTotalPrice = 150;

Esse cuidado também aparece nos princípios de clean code, que tratam nomes como a primeira forma de documentação do código.

2. Use camel case

Camel case é uma convenção de nomes muito usada para variáveis em JavaScript e em outras linguagens. Nesse padrão, a primeira palavra começa com letra minúscula e cada palavra seguinte começa com letra maiúscula.

Como exemplo, podemos citar productTotalPrice, productQuantity e isActiveStudent. Assim, o nome fica legível mesmo sem espaços.

Por convenção, muitos times também usam letras maiúsculas com sublinhado para constantes de configuração, como MAX_RETRIES. Já nomes que começam com maiúscula, como Person, costumam ficar reservados para classes.

3. Evite palavras reservadas e nomes confusos

O JavaScript tem um conjunto de palavras reservadas que a linguagem reconhece internamente, como var, let, const, function, class, return e if. Por isso, você não pode usá-las como nome de variável, e o código abaixo nem chega a executar.

var var = [1, 2];    // SyntaxError
let class = "math";  // SyntaxError

Por outro lado, palavras como number e string não são reservadas no JavaScript, mas lembram nomes de tipos e confundem quem lê o código. Portanto, o ideal é evitá-las também e optar por nomes que descrevam melhor o conteúdo.

// confuso, embora funcione
var number = 1;
var string = "text";

// melhor
let attempts = 1;
let welcomeMessage = "text";

A lista completa de palavras reservadas está na gramática léxica da MDN.

4. Use o plural para listas

É muito comum esquecer o plural ao nomear listas. No entanto, sempre que a variável puder guardar um ou mais itens, o nome deve ficar no plural.

const names = ["José", "Pedro", "Henrique"];

const schools = ["School1", "School2", "School3"];

Dessa maneira, fica muito mais claro que existe mais de um item dentro da variável. Além disso, nomes no plural combinam bem com laços, como em for (const name of names).

5. Prefixe booleanos com is, has ou can

Variáveis booleanas ficam mais legíveis quando o nome parece uma pergunta. Por exemplo, isActive, hasPermission e canEdit deixam claro que o valor é verdadeiro ou falso.

Assim, uma condição como if (hasPermission) se lê quase como uma frase. Isso reduz a chance de interpretar errado a lógica do código.

Erros comuns com variáveis no JavaScript

Mesmo depois de entender a teoria, alguns deslizes aparecem com frequência no dia a dia. Por isso, vale conhecer os mais comuns.

O primeiro é tentar reatribuir uma constante. Nesse caso, o motor lança um TypeError, então troque a declaração para let se o valor realmente precisa mudar.

O segundo é usar uma variável let ou const antes da linha de declaração. Como vimos, isso gera um ReferenceError por causa da zona morta temporal.

O terceiro é achar que copiar um objeto com = cria um objeto novo. Na verdade, as duas variáveis passam a apontar para o mesmo dado na memória.

Por fim, declarar tudo no escopo global aumenta o risco de conflito de nomes entre arquivos e bibliotecas. Mantenha as variáveis no JavaScript dentro das funções e blocos que realmente as usam.

O que podemos concluir

Usar variáveis no JavaScript é essencial sempre que precisamos armazenar valores na memória. Existem diferentes formas de declaração, e você deve escolher a mais adequada com base no contexto da sua aplicação.

Em geral, prefira const, use let quando o valor precisar mudar e reserve o var para código legado. Além disso, lembre que tipos primitivos são copiados por valor, enquanto objetos e arrays são compartilhados por referência.

Também vale adotar boas práticas de nomenclatura, porque nomes claros tornam o código mais fácil de ler e manter. Como próximo passo, continue estudando com o artigo sobre funções no JavaScript.

Eu espero que você tenha gostado desta leitura. Te vejo na próxima, bons códigos!

FAQ

Qual a diferença entre var, let e const?

O var tem escopo de função e permite redeclaração, enquanto let e const têm escopo de bloco. Além disso, o const não permite reatribuir o valor.

Devo usar const ou let por padrão?

Muitos guias recomendam const por padrão. Assim, você só usa let quando o valor realmente precisa mudar.

O const deixa um objeto imutável?

Não, ele apenas impede a reatribuição da variável. As propriedades do objeto continuam podendo ser alteradas.

Preciso informar o tipo da variável no JavaScript?

Não, porque o JavaScript tem tipagem dinâmica. O tipo acompanha o valor atribuído e pode ser consultado com typeof.

Por que alterar uma cópia de array muda o original?

Porque arrays e objetos são atribuídos por referência. Para obter uma cópia independente, use o spread, como em [...list].

Glossário

Termo Significado
Variável Nome que aponta para um valor armazenado na memória.
Escopo Região do código em que uma variável pode ser acessada.
Escopo de bloco Visibilidade limitada ao trecho entre chaves onde a variável foi declarada.
Hoisting Comportamento em que declarações são processadas antes da execução do código.
Zona morta temporal Trecho anterior à declaração de let ou const em que o acesso gera ReferenceError.
Tipo primitivo Valor simples, como number, string, boolean, undefined, null, bigint e symbol.
Referência Endereço que aponta para um objeto ou array na memória.
Camel case Convenção em que a primeira palavra é minúscula e as seguintes começam com maiúscula.

Fontes