Saltar al contenido
objetos.js · devschool

Objetos en JavaScript

Lección 16 de 38 · 10 min de lectura · Actualizado el

En esta lección
  1. Crear un objeto
  2. Leer y cambiar propiedades
  3. Objetos dentro de objetos
  4. Métodos y this
  5. Comprobar si existe una propiedad
  6. Recorrer un objeto
  7. Object.assign y Object.freeze
  8. Referencias frente a copias
  9. Comparar objetos
  10. Arrays de objetos
  11. JSON
  12. Errores frecuentes
  13. Resumen

Un objeto agrupa datos relacionados bajo nombres. Si un array es una lista, un objeto es una ficha: la ficha de un usuario, de un producto, de un pedido. Casi todo en JavaScript es un objeto o se comporta como uno, y los datos que recibes de un servidor llegan como objetos. En esta lección aprenderás a crearlos, leerlos y modificarlos, a darles comportamiento con métodos, a recorrerlos y a evitar la trampa más común: creer que has copiado un objeto cuando solo has copiado una referencia.

Crear un objeto

La forma habitual es el literal de objeto: unas llaves con propiedades dentro.

const usuario = {
  nombre: "Ana",
  edad: 28,
  ciudad: "Santander",
  esPremium: false,
};

Cada línea es una propiedad: un nombre (la clave), dos puntos y un valor. Se separan con comas. La coma después de la última propiedad es opcional, pero conviene ponerla: al añadir otra línea no se te olvidará.

Las claves son textos. Si una clave no es un nombre válido de variable (lleva espacios o guiones), hay que escribirla entre comillas:

const ficha = {
  "fecha-alta": "2026-09-01",
  "codigo postal": "39001",
};

Un objeto vacío es simplemente {}, y puedes ir rellenándolo después.

Leer y cambiar propiedades

Con punto

Es la forma más cómoda y la que usarás casi siempre:

console.log(usuario.nombre); // Ana
usuario.edad = 29;           // cambia la edad
usuario.email = "ana@ejemplo.com"; // añade una propiedad nueva
delete usuario.esPremium;          // borra una propiedad
console.log(usuario);
// { nombre: 'Ana', edad: 29, ciudad: 'Santander', email: 'ana@ejemplo.com' }

Asignar a una propiedad que no existe la crea. delete la elimina por completo.

Con corchetes

Los corchetes reciben un texto con el nombre de la propiedad. Son imprescindibles en dos casos: cuando el nombre está en una variable y cuando la clave no es un nombre válido:

const campo = "ciudad";
console.log(usuario[campo]);          // Santander
console.log(ficha["codigo postal"]);  // 39001

Ojo con la diferencia: usuario.campo busca una propiedad llamada literalmente "campo"; usuario[campo] usa el valor de la variable.

Un uso muy práctico es contar cosas:

const votos = {};
const papeletas = ["rojo", "azul", "rojo", "verde", "rojo"];

for (const color of papeletas) {
  votos[color] = (votos[color] ?? 0) + 1;
}
console.log(votos); // { rojo: 3, azul: 1, verde: 1 }

Si pides una propiedad que no existe, obtienes undefined (no da error). Pero si intentas leer una propiedad de undefined, sí falla. Para acceder con seguridad a propiedades que quizá no existan, usa ?.:

const pedido = { id: 7 };
console.log(pedido.cliente);          // undefined
console.log(pedido.cliente?.nombre);  // undefined
// pedido.cliente.nombre → TypeError: Cannot read properties of undefined (reading 'nombre')

Claves computadas

Al crear el objeto, también puedes usar corchetes en la clave para calcular su nombre:

const idioma = "es";
const traducciones = {
  [idioma]: "Hola",
  [`saludo_${idioma}`]: "Buenos días",
};
console.log(traducciones); // { es: 'Hola', saludo_es: 'Buenos días' }

Propiedades abreviadas (shorthand)

Si la variable se llama igual que la propiedad, no hace falta repetirla:

const nombre = "Raúl";
const edad = 34;

const socio = { nombre, edad }; // igual que { nombre: nombre, edad: edad }
console.log(socio); // { nombre: 'Raúl', edad: 34 }

Lo verás constantemente en código moderno, sobre todo al construir objetos dentro de funciones.

Objetos dentro de objetos

Los valores pueden ser cualquier cosa, incluidos arrays y otros objetos:

const pedido = {
  id: 1024,
  cliente: { nombre: "Luis", email: "luis@ejemplo.com" },
  productos: ["teclado", "ratón"],
};

pedido.cliente.nombre   // "Luis"
pedido.productos[0]     // "teclado"

Se leen encadenando de izquierda a derecha: “del pedido, el cliente; del cliente, el nombre”.

Métodos y this

Una propiedad cuyo valor es una función se llama método. Dentro, this se refiere al objeto que llama al método:

const contador = {
  valor: 0,
  sumar() {
    this.valor++;
  },
  reiniciar() {
    this.valor = 0;
  },
};

contador.sumar();
contador.sumar();
console.log(contador.valor); // 2

Ya conoces muchos métodos: console.log es el método log del objeto console, y "hola".toUpperCase() es un método de las cadenas.

Un ejemplo más realista, una cuenta del gimnasio:

const cuenta = {
  titular: "Nerea",
  sesiones: 10,
  usarSesion() {
    if (this.sesiones === 0) return "Sin sesiones: renueva el bono";
    this.sesiones--;
    return `${this.titular}, te quedan ${this.sesiones} sesiones`;
  },
};

console.log(cuenta.usarSesion()); // Nerea, te quedan 9 sesiones

Cuidado: no escribas los métodos como funciones flecha (usarSesion: () => {...}). Las funciones flecha no tienen su propio this, así que this.sesiones no apuntaría al objeto. Usa la forma corta usarSesion() {...}.

Cuando necesites crear muchos objetos con los mismos métodos (cien cuentas, no una), lo adecuado son las clases.

Comprobar si existe una propiedad

Comparar con undefined no siempre sirve, porque una propiedad puede existir y valer undefined. Hay dos formas fiables:

const producto = { nombre: "Taza", precio: 8, oferta: undefined };

console.log("precio" in producto);             // true
console.log("oferta" in producto);             // true
console.log("stock" in producto);              // false
console.log(Object.hasOwn(producto, "precio")); // true
  • El operador in devuelve true si la propiedad existe en el objeto o en lo que hereda (por ejemplo, "toString" in producto es true).
  • Object.hasOwn(obj, clave) solo mira las propiedades propias del objeto. Es la forma moderna recomendada.

Recorrer un objeto

Tienes for...in (visto en bucles) y, sobre todo, tres funciones que convierten el objeto en un array:

const notas = { mates: 7, lengua: 8, historia: 5 };

console.log(Object.keys(notas));    // [ 'mates', 'lengua', 'historia' ]
console.log(Object.values(notas));  // [ 7, 8, 5 ]
console.log(Object.entries(notas)); // [ [ 'mates', 7 ], [ 'lengua', 8 ], [ 'historia', 5 ] ]

Como el resultado es un array, puedes usar for...of y todos los métodos de arrays:

for (const [asignatura, nota] of Object.entries(notas)) {
  console.log(`${asignatura}: ${nota}`);
}

const valores = Object.values(notas);
const media = valores.reduce((suma, n) => suma + n, 0) / valores.length;
console.log(media.toFixed(2)); // 6.67
console.log(Object.keys(notas).length); // 3 (número de propiedades)

Object.fromEntries hace el camino inverso: de un array de pares a un objeto. Juntos permiten transformar objetos:

const conIva = Object.fromEntries(
  Object.entries({ cafe: 1, tostada: 2 }).map(([k, v]) => [k, v * 1.1])
);
console.log(conIva); // { cafe: 1.1, tostada: 2.2 }

Object.assign y Object.freeze

Object.assign(destino, origen) copia las propiedades de uno o varios objetos en el destino. Sirve, por ejemplo, para aplicar opciones por defecto:

const porDefecto = { tema: "claro", idioma: "es", avisos: true };
const elegidas = { tema: "oscuro" };

const config = Object.assign({}, porDefecto, elegidas);
console.log(config); // { tema: 'oscuro', idioma: 'es', avisos: true }

Las propiedades de los últimos objetos pisan a las anteriores. Hoy es más habitual escribirlo con spread, { ...porDefecto, ...elegidas }, que verás en desestructuración y spread.

Object.freeze(obj) congela un objeto: ya no se pueden añadir, cambiar ni borrar propiedades. Recuerda que const solo impide reasignar la variable; freeze protege el contenido:

const TARIFAS = Object.freeze({ basica: 25, premium: 40 });
TARIFAS.basica = 0;       // se ignora (en modo estricto, TypeError)
console.log(TARIFAS.basica); // 25

freeze es superficial: si una propiedad es otro objeto, ese objeto interior sí se puede modificar.

Referencias frente a copias

Esta es la idea más importante de la lección. Una variable con un número guarda el número. Una variable con un objeto guarda una referencia: una dirección que apunta al objeto. Si asignas esa variable a otra, copias la dirección, no el objeto:

const original = { nombre: "Ana", puntos: 10 };
const otra = original;   // misma referencia, mismo objeto

otra.puntos = 99;
console.log(original.puntos); // 99

Solo hay un objeto con dos nombres. Lo mismo pasa al pasar un objeto a una función: si la función lo modifica, modifica el original.

Para tener un objeto independiente hay que copiarlo:

const copia = { ...original };  // o Object.assign({}, original)
copia.puntos = 0;
console.log(original.puntos); // 99 (no cambia)

Esa copia es superficial: los objetos y arrays de dentro siguen compartidos. Para copiar también el interior existe structuredClone(obj). Tienes la explicación completa, con ejemplos, en copia superficial frente a copia profunda.

Comparar objetos

Por la misma razón, === con objetos compara referencias, no contenido:

const a = { talla: "M" };
const b = { talla: "M" };
const c = a;

console.log(a === b); // false (dos objetos distintos, aunque iguales)
console.log(a === c); // true  (el mismo objeto)

Para saber si dos objetos tienen el mismo contenido, compara sus propiedades. Si son objetos simples sin métodos, un truco rápido es compararlos como texto con JSON.stringify (el orden de las claves debe coincidir):

console.log(JSON.stringify(a) === JSON.stringify(b)); // true

Arrays de objetos

Es la forma más habitual de guardar datos en una aplicación: una lista de fichas.

const alumnos = [
  { nombre: "Ana", nota: 8 },
  { nombre: "Luis", nota: 4 },
  { nombre: "Eva", nota: 6 },
];

const aprobados = alumnos.filter((a) => a.nota >= 5);
const nombres = alumnos.map((a) => a.nombre); // ["Ana", "Luis", "Eva"]
const luis = alumnos.find((a) => a.nombre === "Luis"); // { nombre: 'Luis', nota: 4 }

Para agrupar fichas por una propiedad existe Object.groupBy, y cuando necesites un diccionario con claves de cualquier tipo, un Map suele ser mejor que un objeto. Ambas cosas están en Set y Map.

JSON

JSON es un formato de texto con la misma forma que los objetos de JavaScript. Es como viajan los datos entre un servidor y tu web:

const texto = JSON.stringify(usuario); // objeto → texto
const deVuelta = JSON.parse(texto);    // texto → objeto

Sus reglas y usos los tienes en la lección de JSON.

Errores frecuentes

  • Usar punto con una variable: usuario.campo en vez de usuario[campo].
  • Leer una propiedad de algo que no existe: pedido.cliente.nombre falla si no hay cliente. Usa pedido.cliente?.nombre.
  • Creer que has copiado un objeto con const copia = original. Solo has copiado la referencia.
  • Comparar objetos con === esperando que compare el contenido.
  • Métodos con función flecha: this no apunta al objeto.
  • Olvidar la coma entre propiedades: SyntaxError.
  • Pensar que const hace el objeto inmutable: para eso está Object.freeze.

Resumen

Quiero…Cómo
Crear un objeto{ clave: valor }
Leer o cambiar una propiedadobj.clave o obj["clave"]
Usar una clave guardada en una variableobj[variable]
Añadir / borrarobj.nueva = 1 / delete obj.clave
Saber si existe una propiedadObject.hasOwn(obj, "clave") o "clave" in obj
Obtener claves, valores o paresObject.keys, Object.values, Object.entries
Combinar objetosObject.assign({}, a, b) o { ...a, ...b }
Impedir cambiosObject.freeze(obj)
Copiar{ ...obj } (superficial) o structuredClone(obj) (profunda)
Comparar contenidopropiedad a propiedad, no con ===

Pruébalo tú

Cambia el código y pulsa Ejecutar (o Ctrl + Enter).

objetos.js
Consola

Pon a prueba lo que has aprendido

[JavaScript] ¿Qué muestra la consola?
const usuario = { nombre: "Ana", edad: 25 };
console.log(usuario.email);

[JavaScript] ¿Cómo lees una propiedad cuyo nombre está guardado en la variable campo?

[JavaScript] ¿Qué muestra este código?
const socio = { nombre: "Ana", cuota: 30 };
const otro = socio;
otro.cuota = 40;
console.log(socio.cuota);

[JavaScript] ¿Qué muestra la consola?
const a = { id: 1 };
const b = { id: 1 };
console.log(a === b);

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.