Sua dose diária de programação

Conceito, 3 exemplos e 3 exercícios: uma pequena conquista de cada vez.

✦   Lição

Variáveis e tipos básicos

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.

JavaScript Fundamentos Iniciante 3 exemplos + 3 exercícios
42 lições publicadas 10 linguagens novas lições todo dia útil
JavaScript / Fundamentos

Variáveis e tipos básicos

por Sloane Kensington
Iniciante

Entenda 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.

↳ Pontos-chave
  • Use const por padrão e let só para valores que serão reatribuídos; evite var em código novo.
  • Os tipos primitivos são string, number, boolean, undefined, null, bigint e symbol.
  • typeof valor devolve o tipo como texto; por uma peculiaridade antiga, typeof null dá 'object'.
  • Com uma string de um dos lados, + concatena: '3' + 1 dá '31'. Converta com Number(...) antes de somar.
  • Conversão que falha gera NaN, que é do tipo number; teste com Number.isNaN(valor).

Do conceito à prática

3 exemplos para ver a ideia funcionando.

01Estoque da loja com const e let

estoque.js
// 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

tipos.js
// 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

conversao.js
// 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.

↳ Requisitos
  • Usar const para receita e vegana e let para porcoes e tempoForno.
  • Declarar tempoForno sem 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.
código inicial
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
saída esperada
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

  1. receita e vegana usam const porque não mudam durante o programa; se alguém tentar trocá-las por engano, o Node avisa com um erro.
  2. porcoes usa let porque o enunciado manda ajustar o número de porções mais adiante.
  3. let tempoForno; declara a variável sem valor. Até receber algo, ela guarda undefined, que é ao mesmo tempo o valor e o tipo.
  4. Em cada linha, o template literal insere o valor com ${receita} e o tipo com ${typeof receita}. typeof devolve o nome do tipo como texto.
  5. porcoes = 12; e tempoForno = 40; reatribuem as variáveis sem a palavra let: ela só aparece na declaração.
  6. As duas últimas linhas repetem a impressão e mostram que tempoForno passou de undefined para number.

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 porcoes por const porcoes faz a linha porcoes = 12; gerar TypeError: Assignment to constant variable.. Use let para o que muda.
  • Repetir o let na reatribuição: let porcoes = 12; no mesmo bloco gera SyntaxError: Identifier 'porcoes' has already been declared. Escreva só porcoes = 12;.
  • Declarar const sem valor: const tempoForno; gera SyntaxError: Missing initializer in const declaration. Constantes precisam de valor na hora.
  • Esperar 'String' com maiúscula: typeof sempre 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.

↳ Requisitos
  • Manter as três notas como strings nas constantes iniciais.
  • Converter cada nota com Number antes de somar.
  • Guardar o resultado da comparação media >= 7 em uma constante e exibir o tipo dela com typeof.
  • A saída deve ser idêntica à saída esperada.
código inicial
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
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
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

  1. 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.
  2. nota1 + nota2 + nota3 usa o + com textos, que concatena: o resultado é '7.589.25', uma string sem sentido como nota.
  3. Number(nota1) converte o texto em number. Com os três valores convertidos, o mesmo + passa a somar: 7,5 + 8 + 9,25 = 24,75.
  4. media divide a soma por 3; como 24,75 / 3 dá exatamente 8,25, o número é impresso sem arredondamento.
  5. media >= 7 é uma comparação, e toda comparação produz um boolean. O resultado vai direto para a constante aprovado.
  6. As linhas com typeof confirmam que media é number e aprovado é 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' em NaN, 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) / 3 divide só a última nota e dá 18,58... Guarde a soma antes ou use parênteses.
  • Usar parseInt em notas decimais: parseInt('7.5') devolve 7 e descarta a parte decimal. Para decimais use Number ou parseFloat.
  • Escrever a nota com vírgula: Number('7,5') devolve NaN; 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.

↳ Requisitos
  • Converter moedas e vidas com Number e ler a espada comparando o texto com ===, sem usar Boolean.
  • Detectar o bônus inválido com Number.isNaN e usar 0 no lugar dele.
  • Imprimir uma linha mostrando que Boolean('false') daria true.
  • A saída deve ser idêntica à saída esperada.
código inicial
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
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
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

  1. As cinco constantes do início imitam um arquivo de save, em que todo dado é gravado como texto. Até o 'false' é uma string.
  2. Number(moedasSalvas) e Number(vidasSalvas) convertem os textos numéricos em number, prontos para contas.
  3. temEspadaSalvo === 'true' compara o texto com 'true' e produz um boolean verdadeiro: true só quando o save diz 'true', e false em qualquer outro caso.
  4. Number('dez') não consegue converter e devolve NaN. Number.isNaN(bonusLido) detecta esse caso, e o operador ternário (condição ? a : b) escolhe 0 quando o valor é inválido.
  5. As linhas com typeof confirmam que cada dado terminou com o tipo certo: string, number, number e boolean.
  6. A linha da armadilha mostra que Boolean('false') dá true, porque qualquer string não vazia é considerada verdadeira.
  7. moedas + bonus soma dois números; com o bônus inválido trocado por 0, o total continua 120 em vez de virar NaN.

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á true para 'false', e o jogador ganha uma espada que não tem. Compare com === 'true'.
  • Testar NaN com ===: bonusLido === NaN é sempre false, porque NaN não é igual nem a si mesmo. Use Number.isNaN(bonusLido).
  • Usar o isNaN global com texto: isNaN('dez') converte antes de testar e mistura "não é número" com "é texto". Number.isNaN só responde true para o valor NaN, o que deixa a intenção clara.
  • Somar sem converter: moedasSalvas + 10 dá '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

Últimas lições

Ver o arquivo completo →