Os tipos de dados em JavaScript
Nesta aula, exploramos os tipos de dados em JavaScript, incluindo primitivos e objetos, suas particularidades, exemplos práticos e pegadinhas comuns como typeof null, NaN e coerção.
Em JavaScript, entender os tipos de dados é fundamental para escrever código correto e previsível. A linguagem possui um sistema de tipos dinâmico e fracamente tipado, o que significa que as variáveis podem conter qualquer tipo de dado e que a coerção automática entre tipos é comum. Nesta aula, vamos detalhar os tipos primitivos e o tipo objeto, suas características, exemplos e as pegadinhas que frequentemente confundem desenvolvedores.
Dominar esses conceitos evita bugs sutis e ajuda a aproveitar melhor os recursos da linguagem. Vamos começar com a classificação dos tipos.
Tipos primitivos e objeto
JavaScript define sete tipos primitivos: string, number, boolean, undefined, null, symbol (ES6) e bigint (ES2020). Todos os demais valores são objetos, incluindo arrays, funções, datas, expressões regulares, etc. Objetos são coleções de pares chave-valor e podem ser criados com a sintaxe literal ou com construtores.
Primitivos são imutáveis e não têm métodos próprios (quando você chama um método em um primitivo, o JavaScript o envolve temporariamente em um objeto wrapper). Já objetos são mutáveis e armazenam referências.
// Primitivos
let nome = 'João';
let idade = 25;
let ativo = true;
let indefinido;
let vazio = null;
let id = Symbol('id');
let big = 123n;
// Objetos
let pessoa = { nome: 'Maria', idade: 30 };
let numeros = [1, 2, 3];
function soma(a, b) { return a + b; }Particularidades de cada tipo
Cada tipo tem comportamentos específicos. String pode ser delimitada por aspas simples, duplas ou crases (template literals). Number inclui inteiros e ponto flutuante, além de valores especiais como Infinity, -Infinity e NaN. Boolean tem dois valores: true e false. Undefined indica ausência de valor, enquanto null é uma atribuição intencional de vazio. Symbol é único e imutável, usado como chave de propriedade. BigInt permite números inteiros arbitrariamente grandes.
Os objetos, por sua vez, têm protótipos e podem ser estendidos. Arrays são objetos com índices numéricos e métodos especiais. Funções são objetos chamáveis.
// Strings
let str1 = 'Olá';
let str2 = "Mundo";
let str3 = `Oi ${str1}`; // template literal
// Numbers
let int = 42;
let float = 3.14;
let inf = Infinity;
let nan = NaN;
// Boolean
let verdade = true;
// Undefined
let x;
console.log(x); // undefined
// Null
let y = null;
// Symbol
let sym = Symbol('chave');
// BigInt
let bigInt = 9007199254740991n;Exemplos
Vamos ver exemplos práticos que mostram como os tipos se comportam em operações comuns. Note a diferença entre primitivos e objetos na comparação e atribuição.
// Comparação de primitivos (por valor)
let a = 'abc';
let b = 'abc';
console.log(a === b); // true
// Comparação de objetos (por referência)
let obj1 = { valor: 10 };
let obj2 = { valor: 10 };
console.log(obj1 === obj2); // false
// Atribuição de primitivos (cópia)
let num1 = 5;
let num2 = num1;
num2 = 10;
console.log(num1); // 5 (não afetado)
// Atribuição de objetos (referência)
let arr1 = [1, 2];
let arr2 = arr1;
arr2.push(3);
console.log(arr1); // [1, 2, 3] (afetado)Pegadinhas (typeof null, NaN, coerção)
JavaScript tem comportamentos surpreendentes. typeof null retorna "object", um erro histórico. NaN (Not-a-Number) é do tipo number e é o único valor que não é igual a si mesmo. A coerção automática pode levar a resultados inesperados, como "5" - 2 resultando em 3 (string convertida para número), mas "5" + 2 resulta em "52" (número convertido para string).
// typeof null
console.log(typeof null); // "object" (pegadinha)
// NaN
console.log(typeof NaN); // "number"
console.log(NaN === NaN); // false
console.log(isNaN(NaN)); // true
// Coerção
console.log('5' - 2); // 3 (string '5' vira número)
console.log('5' + 2); // "52" (número 2 vira string)
console.log('5' * '2'); // 10 (ambos viram números)
console.log(true + 1); // 2 (true vira 1)
console.log(false + 1); // 1 (false vira 0)
console.log(null + 1); // 1 (null vira 0)
console.log(undefined + 1); // NaN (undefined vira NaN)Boas práticas
Para evitar problemas, use sempre === (igualdade estrita) em vez de ==, pois o == faz coerção de tipos. Verifique NaN com Number.isNaN() em vez de isNaN() global. Lembre-se de que null e undefined são diferentes: null é atribuído intencionalmente, undefined indica ausência de atribuição. Ao trabalhar com objetos, cuidado com mutações indesejadas.
Referências
- MDN - Estruturas de dados
- MDN - typeof
- MDN - NaN
- MDN - Comparações de igualdade
- MDN - Symbol
- MDN - BigInt
Exercícios
Qual é o resultado de
typeof null? Por que isso é considerado uma pegadinha?✓ Resposta:typeof nullretorna"object". Isso é uma pegadinha porquenullé um tipo primitivo, mas o operadortypeofretorna incorretamente"object"devido a um bug histórico no JavaScript que não pode ser corrigido por questões de compatibilidade.Explique por que
NaN === NaNretornafalse.✓ Resposta: De acordo com a especificação IEEE 754 para números de ponto flutuante,NaN(Not-a-Number) não é igual a si mesmo. Isso é intencional para indicar que o resultado de uma operação inválida não é um número. Para verificar se um valor éNaN, useNumber.isNaN().Qual o resultado de
"10" + 5e"10" - 5? Explique a diferença.✓ Resposta:"10" + 5resulta em"105"(string), pois o operador+com uma string realiza concatenação. Já"10" - 5resulta em5(número), porque o operador-força a conversão da string para número.O que é um tipo primitivo? Dê exemplos.
✓ Resposta: Tipos primitivos são tipos de dados imutáveis e não são objetos. Em JavaScript, são:string,number,boolean,undefined,null,symbolebigint. Exemplos:'Olá',42,true,undefined,null,Symbol('id'),123n.Qual a diferença entre
undefinedenull?✓ Resposta:undefinedé o valor padrão de variáveis declaradas mas não inicializadas, e indica ausência de valor.nullé um valor atribuído intencionalmente para representar vazio ou nenhum objeto. Eles são diferentes:undefined === nullretornafalse, masundefined == nullretornatruedevido à coerção.