Menu

Tipos primitivos em JavaScript: os 7 valores nativos

Conheça os sete tipos primitivos do JavaScript — string, number, bigint, boolean, null, undefined e symbol — e entenda o que separa eles dos objetos.

Os sete tipos primitivos e o resto

O JavaScript divide os valores em dois grupos. De um lado, sete tipos primitivos — valores simples e imutáveis. Do outro, os objetos — tudo que é composto, mutável ou invocável. Esse é o sistema de tipos da linguagem no nível dos valores.

Os sete tipos primitivos do JavaScript são:

index.js
Output
Click Run to see the output here.

Tudo que não estiver nessa lista — arrays, funções, datas, regex, um {} simples — é objeto. O typeof devolve o tipo em tempo de execução, e você vai reparar naquele bug famoso na última linha. typeof null retorna 'object' desde 1995 e nunca vai ser corrigido: tem código demais no mundo dependendo desse comportamento.

Um primitivo é um valor, não um recipiente

O modelo mental que mais ajuda é este: um primitivo é o próprio valor. O número 3 não é uma caixinha guardando o 3 — ele é só o 3. Duas variáveis com 3 não guardam cópias apontando para algo compartilhado; elas carregam o mesmo valor, ponto:

index.js
Output
Click Run to see the output here.

Os primitivos são comparados por valor. Já os objetos, por referência. Essa única distinção está por trás de muitos momentos do tipo "por que isso deu false?" mais pra frente, principalmente quando você tenta comparar arrays ou objetos com ===.

Primitivos são imutáveis

Não dá pra modificar um primitivo. Toda operação que parece mutação, na verdade, gera um novo valor:

index.js
Output
Click Run to see the output here.

A primeira chamada cria uma string nova e joga fora, porque ninguém guardou o valor de retorno. Já a segunda reatribui name. A string original "ada" nunca foi alterada — nem teria como ser. Com números é a mesma coisa: x + 1 gera um número novo, não modifica o x.

É por isso que usar const com string ou número é realmente seguro. O valor em si não muda, e o const ainda te impede de reatribuir a variável.

Number, BigInt e por que existem dois tipos numéricos

O number do JavaScript é um float de 64 bits. Isso significa aritmética rápida, mas também um limite: inteiros só são exatos até Number.MAX_SAFE_INTEGER (2^53 - 1):

index.js
Output
Click Run to see the output here.

Depois desse limite, os inteiros começam a colidir. O bigint existe justamente para inteiros que precisam continuar exatos em qualquer tamanho. Para criar um, basta adicionar o sufixo n:

index.js
Output
Click Run to see the output here.

bigint e number não se misturam em operações aritméticas — se misturassem, você perderia justamente o ganho de precisão. Use bigint quando precisar lidar com IDs de banco de dados, timestamps em nanossegundos ou criptografia. Para contas do dia a dia, fique com number.

Strings também são primitivos

Em JavaScript, uma string é um tipo primitivo, não um objeto — mesmo que exponha métodos como .length, .slice e .toUpperCase:

index.js
Output
Click Run to see the output here.

Nos bastidores, quando você chama um método em uma string, o JavaScript embrulha ela rapidamente em um objeto String só para a chamada funcionar e depois descarta esse invólucro. Você não precisa se preocupar com isso — o importante é saber que strings se comportam como valores (imutáveis, comparadas por valor), mesmo tendo um monte de métodos disponíveis.

Aspas simples, aspas duplas e crases criam exatamente o mesmo tipo. A diferença é que as crases permitem interpolação e strings com múltiplas linhas, assunto do próximo doc.

null vs undefined

Existem dois primitivos que representam "sem valor", e eles não são intercambiáveis.

O undefined aparece quando algo nunca recebeu um valor — uma variável declarada mas sem atribuição, um argumento de função que não foi passado, uma propriedade que não existe:

index.js
Output
Click Run to see the output here.

null é o que você escreve quando quer dizer "vazio de propósito":

index.js
Output
Click Run to see the output here.

A convenção mais ou menos aceita é essa: undefined é o jeito da linguagem dizer "não tem nada aqui", enquanto null é o jeito do programador dizer a mesma coisa. Os dois são falsy, os dois falham em comparações de igualdade com valores comuns, e cada um vai ganhar uma página dedicada mais pra frente.

Symbols: únicos por construção

symbol é o primitivo menos usado de todos. Todo symbol que você cria é único, mesmo que dois sejam criados a partir da mesma descrição:

index.js
Output
Click Run to see the output here.

Os Symbol são úteis como chaves de objeto que não entram em conflito com as existentes — uma biblioteca pode anexar metadados aos seus objetos usando um Symbol e ter certeza de que nenhum outro código vai sobrescrever. Você vai reencontrá-los mais pra frente ao estudar iteradores e os chamados well-known symbols, como Symbol.iterator.

Verificando tipos em tempo de execução com typeof

O operador typeof resolve a maioria dos casos. Só fique atento a algumas peculiaridades:

index.js
Output
Click Run to see the output here.

Para null, compare diretamente: value === null. Para arrays, use Array.isArray(value). Para "isso é algum primitivo?" não existe um método nativo único, mas o idioma é bem direto:

index.js
Output
Click Run to see the output here.

Primitivos vs Objetos: a pegadinha da atribuição

Vale a pena ver mais uma coisa antes de seguir em frente. Como primitivos são valores e objetos são referências, a atribuição se comporta de um jeito bem diferente:

index.js
Output
Click Run to see the output here.

Com primitivos, b = a copia o valor. Já com objetos, y = x copia a referência — os dois nomes apontam para o mesmo objeto subjacente. Alterar por um dos nomes afeta o outro. Essa é, de longe, a maior fonte de bugs do tipo "peraí, por que isso mudou?" em JavaScript.

O que levar desta lição

  • Sete tipos primitivos em JavaScript: string, number, bigint, boolean, null, undefined e symbol. Todo o resto é objeto.
  • Primitivos são imutáveis e comparados por valor; objetos são mutáveis e comparados por referência.
  • O operador typeof informa o tipo em tempo de execução, com duas pegadinhas que vale decorar: typeof null === "object" e typeof function(){} // "function".
  • number é um ponto flutuante de 64 bits com um limite seguro para inteiros; bigint existe justamente para inteiros exatos acima desse limite.

A seguir: strings e template literals

A string é o primitivo com que você vai lidar o tempo todo, e os template literals (aquelas strings com crase) tornam a construção delas indolor — interpolação, texto multilinha e tagged templates. É o assunto da próxima página.

Perguntas frequentes

Quantos tipos primitivos existem em JavaScript?

São sete: string, number, bigint, boolean, null, undefined e symbol. Todo o resto — arrays, funções, datas, objetos comuns — é objeto. Para descobrir o tipo de um valor em tempo de execução, use typeof. Só tem uma pegadinha histórica: typeof null devolve 'object'.

Qual a diferença entre um primitivo e um objeto em JavaScript?

Primitivos são valores imutáveis e comparados por valor — dois 3 são o mesmo 3. Objetos são mutáveis e comparados por referência — dois {} são considerados diferentes mesmo parecendo iguais. Ao atribuir um primitivo, o valor é copiado; ao atribuir um objeto, o que se copia é a referência para os mesmos dados.

Os primitivos em JavaScript são realmente imutáveis?

São sim. Você não consegue alterar um primitivo no lugar — 'hello'.toUpperCase() retorna uma string nova, não mexe na original. Quando você reatribui uma variável (x = x + 1), está apenas trocando o valor dela por outro primitivo; o valor antigo continua intacto. É por isso que const name = 'Ada' ainda permite criar novas strings a partir de name.

Por que typeof null retorna 'object'?

É um bug da implementação original de 1995 que nunca foi corrigido porque já tinha muito código dependendo desse comportamento. Para testar se algo é null, compare com ===: value === null. Para testar undefined, use value === undefined ou typeof value === 'undefined'.

Aprenda a programar com o Coddy

COMEÇAR