Variáveis e tipos básicos
por Sloane KensingtonEntenda o conceito
Uma variável é um nome que aponta para um valor. Em JavaScript moderno você declara variáveis com const, quando o valor não vai ser trocado, ou com let, quando ele precisa mudar ao longo do programa. A palavra antiga var ainda funciona, mas tem regras de escopo confusas e não é usada em código novo. A boa prática é começar com const e trocar para let só quando precisar reatribuir.
Todo valor tem um tipo. Os tipos primitivos são string (texto), number (inteiros e decimais, no mesmo tipo), boolean (true ou false), undefined (variável sem valor), null (ausência de valor proposital), bigint (inteiros muito grandes, com n no final) e symbol. O operador typeof devolve o nome do tipo como texto, por exemplo typeof 42 dá 'number'.
JavaScript tem tipagem dinâmica: a variável não tem tipo fixo, o tipo é do valor guardado nela naquele momento. Isso dá flexibilidade, mas exige atenção às conversões. Dados que vêm de fora (formulários, arquivos) chegam como texto, e o + com texto concatena em vez de somar. Use Number(...), String(...) e Boolean(...) para converter de forma explícita.
- Use
constpor padrão eletsó para valores que serão reatribuídos; evitevarem código novo. - Os tipos primitivos são
string,number,boolean,undefined,null,bigintesymbol. typeof valordevolve o tipo como texto; por uma peculiaridade antiga,typeof nulldá'object'.- Com uma string de um dos lados,
+concatena:'3' + 1dá'31'. Converta comNumber(...)antes de somar. - Conversão que falha gera
NaN, que é do tiponumber; teste comNumber.isNaN(valor).
Do conceito à prática
3 exemplos para ver a ideia funcionando.
01Estoque da loja com const e let
// Controle simples de estoque: const para o que não muda, let para o que muda.
// O nome e o preço do produto não vão mudar neste programa
const produto = 'Caneta azul';
const preco = 2.5;
// A quantidade em estoque muda a cada venda, então usamos let
let estoque = 40;
console.log(`Início: ${estoque} unidades de ${produto}`);
// Venda de 12 unidades: o novo valor substitui o antigo
estoque = estoque - 12;
console.log(`Depois da venda: ${estoque} unidades`);
// Chegada de mercadoria: += soma e guarda na mesma variável
estoque += 25;
console.log(`Depois da reposição: ${estoque} unidades`);
// O valor do estoque é calculado a partir das duas variáveis
const valorEmEstoque = estoque * preco;
console.log(`Valor parado no estoque: R$ ${valorEmEstoque}`);
// let também pode começar vazia e receber o valor depois
let ultimaVenda;
console.log('Última venda registrada:', ultimaVenda);
ultimaVenda = '16/10';
console.log('Última venda registrada:', ultimaVenda);
O nome e o preço do produto ficam em const, porque não mudam, enquanto o estoque usa let, já que cada venda e cada reposição troca o valor guardado. Na reatribuição não se repete a palavra let: ela só aparece na declaração. O operador += é um atalho para estoque = estoque + 25.
As últimas linhas mostram que uma variável declarada com let e sem valor guarda undefined até receber algo. Com const isso não é permitido: a constante precisa de valor no momento em que é declarada.
02Os tipos primitivos no acervo da biblioteca
// Os tipos primitivos do JavaScript, vistos com o operador typeof.
const titulo = 'Dom Casmurro'; // string: texto
const paginas = 256; // number: inteiros e decimais
const multaPorDia = 0.75; // também number
const emprestado = true; // boolean: true ou false
let devolucao; // undefined: declarada sem valor
const leitorReserva = null; // null: "nenhum valor", de propósito
const codigoAcervo = 9007199254740993n; // bigint: inteiros enormes
console.log(typeof titulo, '->', titulo);
console.log(typeof paginas, '->', paginas);
console.log(typeof multaPorDia, '->', multaPorDia);
console.log(typeof emprestado, '->', emprestado);
console.log(typeof devolucao, '->', devolucao);
console.log(typeof codigoAcervo, '->', codigoAcervo);
// Peculiaridade histórica da linguagem: typeof null devolve 'object'
console.log(typeof leitorReserva, '->', leitorReserva);
// Para testar null, compare diretamente com ===
console.log('Sem reserva?', leitorReserva === null);
// A variável não tem tipo fixo: o tipo é do valor guardado nela
let situacao = 'disponível';
console.log(typeof situacao);
situacao = 3; // agora guarda um número
console.log(typeof situacao);
Cada constante guarda um tipo primitivo diferente, e typeof mostra o nome de cada um. Repare que inteiros (256) e decimais (0.75) são do mesmo tipo number, e que o bigint é escrito com n no final. A linha de null mostra a peculiaridade mais famosa da linguagem: typeof null devolve 'object', então o teste correto é leitorReserva === null.
O final do exemplo mostra a tipagem dinâmica: a mesma variável situacao guarda primeiro um texto e depois um número, e typeof acompanha o valor atual.
03Convertendo os dados de um pedido
// Convertendo os dados de um formulário de pedido, que sempre chegam como texto.
const qtdDigitada = '3';
const precoDigitado = '19.90';
const cupomDigitado = 'abc';
// O + com texto concatena em vez de somar
console.log('Sem converter:', qtdDigitada + 1);
// Number converte o texto inteiro em número
const quantidade = Number(qtdDigitada);
const preco = Number(precoDigitado);
console.log('Convertido:', quantidade + 1, typeof quantidade);
// Texto que não é número vira NaN (Not a Number), que ainda é do tipo number
const desconto = Number(cupomDigitado);
console.log('Desconto:', desconto, typeof desconto);
console.log('Desconto inválido?', Number.isNaN(desconto));
// Decimais em ponto flutuante têm pequenas imprecisões
const total = quantidade * preco;
console.log('Total bruto:', total);
console.log('Total formatado:', total.toFixed(2));
// String e Boolean fazem as conversões no sentido contrário
console.log(String(quantidade) + ' itens');
console.log('Boolean(0):', Boolean(0), '| Boolean(""):', Boolean(''));
console.log('Boolean("0"):', Boolean('0'), '| Boolean(5):', Boolean(5));
Dados digitados chegam como texto, e '3' + 1 dá '31': o + concatena quando um dos lados é string. Depois de Number(...), a mesma conta dá 4. Um texto que não representa número vira NaN, que curiosamente é do tipo number; Number.isNaN é a forma confiável de detectá-lo.
O total 59.699999999999996 mostra a imprecisão normal dos decimais em ponto flutuante, e toFixed(2) resolve a exibição. Por fim, Boolean revela quais valores são falsos: 0 e a string vazia dão false, mas a string '0' dá true, porque não está vazia.
Agora é com você
Tente resolver no rascunho antes de abrir a resposta. Os códigos não são executados nesta página.
01Ficha de receita com tiposFácil
Declare as variáveis de uma receita de bolo de cenoura (nome, porções, se é vegana e o tempo de forno ainda indefinido) e imprima o valor e o tipo de cada uma. Depois ajuste as porções para 12 e o tempo de forno para 40 e imprima essas duas de novo.
- Usar
constparareceitaeveganaeletparaporcoesetempoForno. - Declarar
tempoFornosem valor inicial. - Mostrar o tipo de cada variável com
typeof, dentro de um template literal. - A saída deve ser idêntica à saída esperada.
const receita = 'Bolo de cenoura';
// declare porcoes (8), vegana (false) e tempoForno (sem valor)
console.log(`receita: ${receita} (${typeof receita})`);
// imprima as outras variáveis, ajuste porcoes e tempoForno e imprima de novo
receita: Bolo de cenoura (string)
porcoes: 8 (number)
vegana: false (boolean)
tempoForno: undefined (undefined)
porcoes: 12 (number)
tempoForno: 40 (number)
Ver dica
Uma variável declarada com let e sem valor já existe; experimente imprimir o tipo dela antes de atribuir qualquer coisa.
Ver resposta
// Ficha de uma receita com valor e tipo de cada variável
const receita = 'Bolo de cenoura';
let porcoes = 8; // vai mudar mais adiante
const vegana = false;
let tempoForno; // ainda sem valor
console.log(`receita: ${receita} (${typeof receita})`);
console.log(`porcoes: ${porcoes} (${typeof porcoes})`);
console.log(`vegana: ${vegana} (${typeof vegana})`);
console.log(`tempoForno: ${tempoForno} (${typeof tempoForno})`);
// Novos valores para as variáveis declaradas com let
porcoes = 12;
tempoForno = 40;
console.log(`porcoes: ${porcoes} (${typeof porcoes})`);
console.log(`tempoForno: ${tempoForno} (${typeof tempoForno})`);
Passo a passo
receitaeveganausamconstporque não mudam durante o programa; se alguém tentar trocá-las por engano, o Node avisa com um erro.porcoesusaletporque o enunciado manda ajustar o número de porções mais adiante.let tempoForno;declara a variável sem valor. Até receber algo, ela guardaundefined, que é ao mesmo tempo o valor e o tipo.- Em cada linha, o template literal insere o valor com
${receita}e o tipo com${typeof receita}.typeofdevolve o nome do tipo como texto. porcoes = 12;etempoForno = 40;reatribuem as variáveis sem a palavralet: ela só aparece na declaração.- As duas últimas linhas repetem a impressão e mostram que
tempoFornopassou deundefinedparanumber.
Por que funciona
Em JavaScript o tipo pertence ao valor, não à variável. typeof olha o valor guardado naquele momento, por isso tempoForno aparece primeiro como undefined e depois como number. A escolha entre const e let diz apenas se a variável pode receber outro valor; ela não muda o tipo dos dados.
Erros comuns
- Reatribuir uma constante: trocar
let porcoesporconst porcoesfaz a linhaporcoes = 12;gerarTypeError: Assignment to constant variable.. Useletpara o que muda. - Repetir o
letna reatribuição:let porcoes = 12;no mesmo bloco geraSyntaxError: Identifier 'porcoes' has already been declared. Escreva sóporcoes = 12;. - Declarar
constsem valor:const tempoForno;geraSyntaxError: Missing initializer in const declaration. Constantes precisam de valor na hora. - Esperar
'String'com maiúscula:typeofsempre devolve nomes em minúsculas, como'string'e'number'.
Outra forma de resolver
Sem template literals, console.log('receita:', receita, '(' + typeof receita + ')') produz a mesma linha, porque console.log separa os argumentos com espaço. Funciona, mas a versão com crases deixa o formato da linha visível de uma vez só.
Saída esperada
receita: Bolo de cenoura (string)
porcoes: 8 (number)
vegana: false (boolean)
tempoForno: undefined (undefined)
porcoes: 12 (number)
tempoForno: 40 (number)
02Média de notas digitadas como textoMédio
As notas de um aluno chegaram do sistema da escola como texto: '7.5', '8' e '9.25'. Mostre o que acontece ao somá-las sem conversão e depois calcule a soma, a média e se o aluno foi aprovado (média maior ou igual a 7), exibindo os tipos do resultado.
- Manter as três notas como strings nas constantes iniciais.
- Converter cada nota com
Numberantes de somar. - Guardar o resultado da comparação
media >= 7em uma constante e exibir o tipo dela comtypeof. - A saída deve ser idêntica à saída esperada.
const nota1 = '7.5';
const nota2 = '8';
const nota3 = '9.25';
// mostre a concatenação, depois converta, calcule a média e a aprovação
Concatenado: 7.589.25
Soma: 24.75
Média: 8.25
Tipo da média: number
Aprovado: true
Tipo de aprovado: boolean
Ver dica
O operador + decide entre juntar textos e somar números olhando o tipo dos dois lados.
Ver resposta
// Notas digitadas no sistema da escola chegam como texto
const nota1 = '7.5';
const nota2 = '8';
const nota3 = '9.25';
// Sem conversão, o + junta os textos
console.log('Concatenado:', nota1 + nota2 + nota3);
// Com Number, o + passa a somar
const soma = Number(nota1) + Number(nota2) + Number(nota3);
const media = soma / 3;
const aprovado = media >= 7; // comparação gera um boolean
console.log('Soma:', soma);
console.log('Média:', media);
console.log('Tipo da média:', typeof media);
console.log('Aprovado:', aprovado);
console.log('Tipo de aprovado:', typeof aprovado);
Passo a passo
- As três notas estão entre aspas, como chegariam de um campo de formulário: são do tipo
string, mesmo parecendo números. nota1 + nota2 + nota3usa o+com textos, que concatena: o resultado é'7.589.25', uma string sem sentido como nota.Number(nota1)converte o texto emnumber. Com os três valores convertidos, o mesmo+passa a somar: 7,5 + 8 + 9,25 = 24,75.mediadivide a soma por 3; como 24,75 / 3 dá exatamente 8,25, o número é impresso sem arredondamento.media >= 7é uma comparação, e toda comparação produz umboolean. O resultado vai direto para a constanteaprovado.- As linhas com
typeofconfirmam quemediaénumbereaprovadoéboolean.
Por que funciona
O operador + decide o que fazer olhando os tipos: se um dos lados é string, ele junta textos; se os dois são números, ele soma. Converter cada nota com Number antes da conta garante que a soma seja numérica. Os outros operadores aritméticos (-, *, /) sempre tentam converter para número, por isso o problema aparece justamente no +.
Erros comuns
- Converter só o resultado:
Number(nota1 + nota2 + nota3)transforma'7.589.25'emNaN, porque a concatenação já aconteceu. Converta cada valor antes de somar. - Esquecer os parênteses na média:
Number(nota1) + Number(nota2) + Number(nota3) / 3divide só a última nota e dá 18,58... Guarde a soma antes ou use parênteses. - Usar
parseIntem notas decimais:parseInt('7.5')devolve7e descarta a parte decimal. Para decimais useNumberouparseFloat. - Escrever a nota com vírgula:
Number('7,5')devolveNaN; o JavaScript só entende o ponto como separador decimal.
Outra forma de resolver
O + unário também converte: +nota1 + +nota2 + +nota3 dá 24.75. É comum em código curto, mas Number(...) deixa a intenção explícita para quem lê, por isso é a melhor escolha ao aprender.
Saída esperada
Concatenado: 7.589.25
Soma: 24.75
Média: 8.25
Tipo da média: number
Aprovado: true
Tipo de aprovado: boolean
03Carregando o save de um jogoDesafio
Um jogo gravou os dados da jogadora como texto: nome 'Lia', moedas '120', vidas '3', espada 'false' e bônus 'dez'. Converta cada valor para o tipo certo, troque o bônus inválido por 0, imprima valores e tipos e mostre o total de moedas com o bônus.
- Converter moedas e vidas com
Numbere ler a espada comparando o texto com===, sem usarBoolean. - Detectar o bônus inválido com
Number.isNaNe usar0no lugar dele. - Imprimir uma linha mostrando que
Boolean('false')dariatrue. - A saída deve ser idêntica à saída esperada.
const nomeSalvo = 'Lia';
const moedasSalvas = '120';
const vidasSalvas = '3';
const temEspadaSalvo = 'false';
const bonusSalvo = 'dez';
// converta cada dado para o tipo certo e imprima o relatório
Jogador: Lia (string)
Moedas: 120 (number)
Vidas: 3 (number)
Tem espada: false (boolean)
Armadilha: Boolean('false') daria true
Bônus lido: NaN, usado: 0
Moedas com bônus: 120
Ver dica
Qualquer string que não esteja vazia é considerada verdadeira, inclusive o texto que diz o contrário.
Ver resposta
// Dados lidos de um arquivo de save: tudo chega como texto
const nomeSalvo = 'Lia';
const moedasSalvas = '120';
const vidasSalvas = '3';
const temEspadaSalvo = 'false';
const bonusSalvo = 'dez';
// Conversões para os tipos certos
const moedas = Number(moedasSalvas);
const vidas = Number(vidasSalvas);
// Comparar com 'true' é o jeito seguro de ler um boolean em texto
const temEspada = temEspadaSalvo === 'true';
const bonusLido = Number(bonusSalvo);
// Valor inválido (NaN) vira 0 para não estragar as contas
const bonus = Number.isNaN(bonusLido) ? 0 : bonusLido;
console.log(`Jogador: ${nomeSalvo} (${typeof nomeSalvo})`);
console.log(`Moedas: ${moedas} (${typeof moedas})`);
console.log(`Vidas: ${vidas} (${typeof vidas})`);
console.log(`Tem espada: ${temEspada} (${typeof temEspada})`);
console.log(`Armadilha: Boolean('false') daria ${Boolean(temEspadaSalvo)}`);
console.log(`Bônus lido: ${bonusLido}, usado: ${bonus}`);
console.log(`Moedas com bônus: ${moedas + bonus}`);
Passo a passo
- As cinco constantes do início imitam um arquivo de save, em que todo dado é gravado como texto. Até o
'false'é uma string. Number(moedasSalvas)eNumber(vidasSalvas)convertem os textos numéricos emnumber, prontos para contas.temEspadaSalvo === 'true'compara o texto com'true'e produz umbooleanverdadeiro:truesó quando o save diz'true', efalseem qualquer outro caso.Number('dez')não consegue converter e devolveNaN.Number.isNaN(bonusLido)detecta esse caso, e o operador ternário (condição ? a : b) escolhe0quando o valor é inválido.- As linhas com
typeofconfirmam que cada dado terminou com o tipo certo:string,number,numbereboolean. - A linha da armadilha mostra que
Boolean('false')dátrue, porque qualquer string não vazia é considerada verdadeira. moedas + bonussoma dois números; com o bônus inválido trocado por0, o total continua120em vez de virarNaN.
Por que funciona
Cada tipo primitivo tem sua forma correta de conversão: Number para números, uma comparação para booleanos e verificação com Number.isNaN para valores que podem falhar. NaN é contagioso: qualquer conta com ele dá NaN, então tratar o valor inválido logo na leitura protege o resto do programa. Como os tipos foram acertados uma vez, no início, as linhas seguintes trabalham só com dados confiáveis.
Erros comuns
- Converter o boolean com
Boolean:const temEspada = Boolean(temEspadaSalvo);dátruepara'false', e o jogador ganha uma espada que não tem. Compare com=== 'true'. - Testar NaN com
===:bonusLido === NaNé semprefalse, porqueNaNnão é igual nem a si mesmo. UseNumber.isNaN(bonusLido). - Usar o
isNaNglobal com texto:isNaN('dez')converte antes de testar e mistura "não é número" com "é texto".Number.isNaNsó respondetruepara o valorNaN, o que deixa a intenção clara. - Somar sem converter:
moedasSalvas + 10dá'12010', uma string. Converta antes de qualquer conta com+.
Outra forma de resolver
O operador || resolve o bônus em uma linha: const bonus = Number(bonusSalvo) || 0;, porque NaN é falso. É curto, mas trata do mesmo jeito um bônus inválido e um bônus legítimo de 0; quando você precisa saber que o valor era inválido (para avisar o jogador, por exemplo), o teste com Number.isNaN é preferível.
Saída esperada
Jogador: Lia (string)
Moedas: 120 (number)
Vidas: 3 (number)
Tem espada: false (boolean)
Armadilha: Boolean('false') daria true
Bônus lido: NaN, usado: 0
Moedas com bônus: 120