Objetos en JavaScript
En esta lección
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 propiothis, así quethis.sesionesno apuntaría al objeto. Usa la forma cortausarSesion() {...}.
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
indevuelvetruesi la propiedad existe en el objeto o en lo que hereda (por ejemplo,"toString" in productoestrue). 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.campoen vez deusuario[campo]. - Leer una propiedad de algo que no existe:
pedido.cliente.nombrefalla si no haycliente. Usapedido.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:
thisno apunta al objeto. - Olvidar la coma entre propiedades:
SyntaxError. - Pensar que
consthace el objeto inmutable: para eso estáObject.freeze.
Resumen
| Quiero… | Cómo |
|---|---|
| Crear un objeto | { clave: valor } |
| Leer o cambiar una propiedad | obj.clave o obj["clave"] |
| Usar una clave guardada en una variable | obj[variable] |
| Añadir / borrar | obj.nueva = 1 / delete obj.clave |
| Saber si existe una propiedad | Object.hasOwn(obj, "clave") o "clave" in obj |
| Obtener claves, valores o pares | Object.keys, Object.values, Object.entries |
| Combinar objetos | Object.assign({}, a, b) o { ...a, ...b } |
| Impedir cambios | Object.freeze(obj) |
| Copiar | { ...obj } (superficial) o structuredClone(obj) (profunda) |
| Comparar contenido | propiedad a propiedad, no con === |
Pruébalo tú
Cambia el código y pulsa Ejecutar (o Ctrl + Enter).
Pon a prueba lo que has aprendido
¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.