Menu

Tipos primitivos en JavaScript: los 7 valores básicos

Los siete tipos primitivos de JavaScript — string, number, bigint, boolean, null, undefined y symbol — y en qué se diferencian de los objetos.

Los siete primitivos y todo lo demás

JavaScript clasifica los valores en dos grandes grupos. Por un lado están los siete tipos primitivos de JavaScript: valores simples e inmutables. Por el otro, los objetos: todo lo que es compuesto, mutable o invocable. Ese es, a nivel de valor, todo el sistema de tipos del lenguaje.

Los siete tipos primitivos son:

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

Todo lo que no esté en esa lista —arrays, funciones, fechas, expresiones regulares, el típico {}— es un objeto. typeof te dice el tipo en tiempo de ejecución, y en la última línea vas a ver la famosa rareza del lenguaje. typeof null devuelve 'object' desde 1995 y nunca se va a arreglar: hay demasiado código existente que depende de ese comportamiento.

Un primitivo es un valor, no un contenedor

El modelo mental que más ayuda es este: un primitivo es su valor. El número 3 no es una caja que contiene un 3: simplemente es 3. Dos variables que guardan 3 guardan el mismo valor, no dos copias apuntando a algo compartido:

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

Los primitivos se comparan por valor. Los objetos, por referencia. Esa pequeña distinción está detrás de muchos momentos del tipo "¿por qué esto da false?" más adelante, sobre todo cuando comparas arrays u objetos con ===.

Los primitivos son inmutables

No puedes modificar un primitivo. Cada operación que parece mutarlo en realidad genera un valor nuevo:

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

La primera llamada crea una cadena nueva y la descarta, porque nadie captura el valor devuelto. La segunda reasigna name. La cadena original "ada" nunca se modificó; no podía hacerlo. Lo mismo pasa con los números: x + 1 produce un número nuevo, no muta x.

Por eso usar const con una cadena o un número es realmente seguro. El valor no puede cambiar, y const te impide reasignar la variable.

Number y BigInt: por qué existen dos tipos numéricos

El tipo number de JavaScript es un float de 64 bits. Eso se traduce en aritmética rápida y un techo: los enteros solo son exactos hasta Number.MAX_SAFE_INTEGER (2^53 - 1):

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

A partir de ese umbral, los enteros empiezan a pisarse entre sí. Para eso existe bigint: números enteros que se mantienen exactos por grandes que sean. Se escriben añadiendo el sufijo n:

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

bigint y number no se pueden mezclar en operaciones aritméticas, porque si lo hicieran perderías justo la precisión extra que ganas con bigint. Úsalo cuando trabajes con IDs de base de datos, timestamps en nanosegundos o temas de criptografía. Para la aritmética de toda la vida, quédate con number.

Los strings también son primitivos

En JavaScript un string es un tipo primitivo, no un objeto, aunque tenga métodos como .length, .slice o .toUpperCase:

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

Por debajo, cuando llamas a un método sobre una cadena, JavaScript la envuelve momentáneamente en un objeto String para que la llamada funcione, y luego descarta ese envoltorio. No hace falta que pienses en él: lo importante es que las cadenas se comportan como valores (son inmutables y se comparan por valor), aunque tengan un montón de métodos disponibles.

Las comillas simples, las dobles y las backticks crean exactamente el mismo tipo. Lo que añaden las backticks es la interpolación y las cadenas multilínea, algo que veremos en el siguiente documento.

null y undefined en JavaScript

Hay dos primitivos que representan "sin valor", y no son intercambiables.

undefined es lo que obtienes cuando algo nunca llegó a asignarse: una variable declarada pero sin valor, un argumento de función que no se pasó, una propiedad que no existe:

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

null es lo que escribes cuando quieres decir "vacío a propósito":

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

La convención más o menos establecida: undefined es la forma que tiene el lenguaje de decir "aquí no hay nada", mientras que null es la forma en que lo dice el programador. Los dos son falsy, los dos fallan al compararlos con valores normales, y cada uno tendrá su propia página más adelante.

Symbol en JavaScript: únicos por construcción

symbol es el primitivo que menos se usa. Cada símbolo que creas es único, incluso si partes de dos descripciones idénticas:

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

Los symbol son útiles como claves de objeto que no pueden chocar con otras ya existentes: una librería puede adjuntar metadatos a tus objetos mediante un símbolo con la certeza de que ningún otro código los sobrescribirá. Volverás a encontrártelos cuando trabajes con iteradores y con los llamados well-known symbols, como Symbol.iterator.

Cómo comprobar tipos en tiempo de ejecución con typeof

El operador typeof en JavaScript resuelve la mayoría de los casos. Eso sí, ten presentes estas rarezas:

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

Para null, compara directamente: value === null. Para arrays, usa Array.isArray(value). No existe una función nativa para preguntar "¿esto es un primitivo cualquiera?", pero el idiom más habitual es bastante claro:

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

Primitivos vs objetos: la trampa de la asignación

Antes de seguir, hay un detalle que merece la pena ver. Como los primitivos son valores y los objetos son referencias, la asignación se comporta de forma distinta en cada caso:

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

Con los primitivos, b = a copia el valor. Con los objetos, y = x copia la referencia: ambos nombres apuntan al mismo objeto subyacente. Si mutas a través de uno, el otro también lo nota. Esta es, sin exagerar, la mayor fuente de bugs del tipo "¿pero por qué cambió eso?" en JavaScript.

Lo que te llevas

  • Siete tipos primitivos: string, number, bigint, boolean, null, undefined y symbol. Todo lo demás es un objeto.
  • Los primitivos son inmutables y se comparan por valor; los objetos son mutables y se comparan por referencia.
  • typeof te dice el tipo en tiempo de ejecución, con dos rarezas que conviene tener siempre presentes: typeof null === "object" y typeof function === "function".
  • number es un número de coma flotante de 64 bits con un techo de seguridad para enteros; bigint existe precisamente para trabajar con enteros exactos más allá de ese techo.

Siguiente: strings y template literals

Los strings son el primitivo que más vas a tocar, y los template literals (esos strings con backticks) hacen que construirlos sea indoloro: interpolación, texto multilínea, tagged templates. De eso va la siguiente página.

Preguntas frecuentes

¿Cuántos tipos primitivos tiene JavaScript?

Siete: string, number, bigint, boolean, null, undefined y symbol. Todo lo demás —arrays, funciones, fechas, objetos planos— es un objeto. Puedes comprobar el tipo de un valor en tiempo de ejecución con typeof, teniendo en cuenta la típica rareza histórica: typeof null devuelve 'object'.

¿Cuál es la diferencia entre un primitivo y un objeto en JavaScript?

Los primitivos son valores inmutables y se comparan por valor: dos 3 son el mismo 3. Los objetos son mutables y se comparan por referencia: dos {} son distintos aunque parezcan iguales. Al asignar un primitivo se copia el valor; al asignar un objeto se copia la referencia al mismo dato en memoria.

¿Los primitivos de JavaScript son realmente inmutables?

Sí. No puedes mutar un primitivo: 'hola'.toUpperCase() devuelve una cadena nueva, no modifica la original. Reasignar una variable (x = x + 1) sustituye el valor que guarda la variable por otro primitivo distinto, pero el valor original nunca cambia. Por eso const name = 'Ada' sigue permitiéndote construir cadenas nuevas a partir de name.

¿Por qué typeof null devuelve 'object'?

Es un bug de la implementación original de 1995 que nunca se corrigió porque había demasiado código que dependía de ese comportamiento. Para detectar null, compara con ===: value === null. Para undefined, usa value === undefined o typeof value === 'undefined'.

Aprende a programar con Coddy

COMENZAR