Skip to content

Objetos ​

Un usuario tiene nombre, correo y edad. Un producto tiene precio, stock y categoría. Para representar "cosas" con varias características, JavaScript usa objetos. Son la estructura de datos más importante del lenguaje: las respuestas de las APIs, la configuración de las librerías y el estado de tus apps son objetos.

Concepto ​

Un objeto es como una ficha de registro: cada campo tiene una etiqueta (la clave o propiedad) y un contenido (el valor). Mientras que un array guarda cosas por posición (0, 1, 2), un objeto las guarda por nombre.

js
const usuario = {
  nombre: 'Ana López',      // clave: valor
  edad: 28,
  activo: true,
  intereses: ['diseño', 'café'],   // un valor puede ser un array
  direccion: {                      // ...u otro objeto
    ciudad: 'Guadalajara',
    cp: '44100'
  }
};

Los valores pueden ser de cualquier tipo, incluso funciones (a esas se les llama métodos).

Acceder y modificar propiedades ​

js
// Notación de punto (la más común)
console.log(usuario.nombre);            // 'Ana López'
console.log(usuario.direccion.ciudad);  // 'Guadalajara'

// Notación de corchetes: cuando la clave está en una variable
// o tiene caracteres especiales
const campo = 'edad';
console.log(usuario[campo]);            // 28

const config = { 'color-fondo': '#fff' };
console.log(config['color-fondo']);

// Modificar
usuario.edad = 29;

// Agregar una propiedad nueva
usuario.telefono = '33 1234 5678';

// Eliminar
delete usuario.activo;

// ¿Existe la propiedad?
console.log('telefono' in usuario);            // true
console.log(Object.hasOwn(usuario, 'activo')); // false

// Leer una propiedad que no existe NO da error: da undefined
console.log(usuario.apellido); // undefined

const no congela el objeto

const usuario = {...} impide reasignar la variable (usuario = otraCosa), pero sí puedes cambiar sus propiedades. Si quieres un objeto realmente inmutable usa Object.freeze(usuario).

Atajos modernos al crear objetos ​

js
const nombre = 'Mouse';
const precio = 349;

// Propiedades abreviadas: si la variable se llama igual que la clave
const producto = { nombre, precio };   // { nombre: 'Mouse', precio: 349 }

// Claves calculadas
const campo = 'color';
const opciones = { [campo]: 'negro', [`${campo}Secundario`]: 'gris' };
// { color: 'negro', colorSecundario: 'gris' }

Métodos y this ​

Un método es una función guardada en un objeto. Dentro de él, this apunta al objeto que lo llamó.

js
const carrito = {
  items: [],
  agregar(producto) {           // sintaxis corta de método
    this.items.push(producto);
    return this;                // permite encadenar
  },
  total() {
    return this.items.reduce((suma, p) => suma + p.precio, 0);
  }
};

carrito.agregar({ nombre: 'Mouse', precio: 349 })
       .agregar({ nombre: 'Teclado', precio: 1299 });

console.log(carrito.total()); // 1648

Error común

No uses funciones flecha como métodos si necesitas this. Las flechas no tienen su propio this: toman el del lugar donde se escribieron.

js
const persona = {
  nombre: 'Luis',
  saludarMal: () => `Hola, soy ${this.nombre}`,   // this NO es persona
  saludarBien() { return `Hola, soy ${this.nombre}`; }
};
persona.saludarMal();  // 'Hola, soy undefined'
persona.saludarBien(); // 'Hola, soy Luis'

Profundizaremos en this en POO y clases.

Recorrer objetos ​

js
const precios = { cafe: 45, te: 35, pan: 20 };

Object.keys(precios);    // ['cafe', 'te', 'pan']
Object.values(precios);  // [45, 35, 20]
Object.entries(precios); // [['cafe', 45], ['te', 35], ['pan', 20]]

// Recorrer con for...of + entries y desestructuración
for (const [producto, precio] of Object.entries(precios)) {
  console.log(`${producto}: $${precio}`);
}

// Sumar valores
const total = Object.values(precios).reduce((a, b) => a + b, 0); // 100

// Transformar un objeto: entries → map → fromEntries
const conDescuento = Object.fromEntries(
  Object.entries(precios).map(([k, v]) => [k, v * 0.9])
);

Desestructuración ​

La desestructuración te permite sacar valores de un objeto o array en variables, en una sola línea.

De objetos ​

js
const pedido = {
  id: 1024,
  cliente: { nombre: 'María', email: 'maria@correo.com' },
  total: 1850,
  estado: 'enviado'
};

// Básica
const { id, total } = pedido;

// Renombrar
const { estado: estadoPedido } = pedido;

// Valor por defecto si no existe
const { metodoPago = 'tarjeta' } = pedido;

// Anidada
const { cliente: { nombre, email } } = pedido;

// En parámetros de función (¡muy usado!)
function mostrarPedido({ id, total, estado = 'pendiente' }) {
  return `Pedido #${id}: $${total} (${estado})`;
}
mostrarPedido(pedido);

Buena práctica

Cuando una función recibe más de 2 o 3 parámetros, pásale un objeto y desestructúralo. Así no importa el orden y el código que la llama se lee solo: crearUsuario({ nombre: 'Ana', rol: 'admin' }).

De arrays ​

js
const colores = ['rojo', 'verde', 'azul', 'negro'];

const [primero, segundo] = colores;      // 'rojo', 'verde'
const [, , tercero] = colores;           // saltar posiciones: 'azul'
const [cabeza, ...resto] = colores;      // 'rojo', ['verde', 'azul', 'negro']

// Intercambiar variables
let a = 1, b = 2;
[a, b] = [b, a];

Spread y rest (...) ​

Los tres puntos hacen dos cosas opuestas según dónde estén:

  • Spread (expandir): "desempaca" un objeto o array.
  • Rest (agrupar): "empaca" lo que sobra.
js
// SPREAD en objetos: copiar y combinar
const base = { color: 'azul', talla: 'M' };
const copia = { ...base };
const actualizado = { ...base, talla: 'L' };     // sobrescribe talla
const combinado = { ...base, ...{ precio: 299 } };

// Configuración con valores por defecto (patrón muy común)
function crearBoton(opciones) {
  const config = { texto: 'Enviar', color: 'primario', deshabilitado: false, ...opciones };
  return config;
}
crearBoton({ color: 'peligro' });
// { texto: 'Enviar', color: 'peligro', deshabilitado: false }

// SPREAD en arrays
const frutas = ['manzana', 'pera'];
const masFrutas = [...frutas, 'uva'];
Math.max(...[3, 9, 2]); // 9

// REST: quitar una propiedad sin mutar
const usuario = { id: 1, nombre: 'Ana', password: '123456' };
const { password, ...usuarioPublico } = usuario;
// usuarioPublico = { id: 1, nombre: 'Ana' }

Copia superficial vs. profunda ​

Los objetos se guardan por referencia: la variable no contiene el objeto, sino la "dirección" donde vive.

js
const original = { nombre: 'Ana' };
const otra = original;      // NO es una copia: es la misma dirección
otra.nombre = 'Luis';
console.log(original.nombre); // 'Luis' 😱

El spread crea una copia superficial: copia el primer nivel, pero los objetos anidados siguen compartidos.

js
const perfil = { nombre: 'Ana', direccion: { ciudad: 'CDMX' } };

const copia = { ...perfil };
copia.nombre = 'Luis';                 // no afecta al original ✅
copia.direccion.ciudad = 'Monterrey';  // ¡sí afecta al original! ❌

// Copia profunda nativa
const copiaProfunda = structuredClone(perfil);
copiaProfunda.direccion.ciudad = 'Puebla'; // el original queda intacto ✅

Error común

Comparar objetos con === compara referencias, no contenido: { a: 1 } === { a: 1 } es false. Para comparar contenido simple puedes usar JSON.stringify(a) === JSON.stringify(b) (cuidado: el orden de las claves importa).

Optional chaining y nullish coalescing ​

Cuando trabajas con datos de APIs, muchas propiedades pueden faltar.

js
const respuesta = { usuario: { perfil: null } };

// Sin optional chaining: error si algo es null/undefined
// respuesta.usuario.perfil.foto  → TypeError

respuesta.usuario?.perfil?.foto;            // undefined, sin error
respuesta.usuario?.perfil?.foto ?? '/img/avatar.png'; // valor por defecto

// También con métodos y corchetes
respuesta.usuario.saludar?.();
respuesta.items?.[0];

Caso real: normalizar la respuesta de una API ​

js
// Lo que llega de una API (estructura incómoda)
const apiUsuario = {
  id: 7,
  name: 'Carlos Ruiz',
  email: 'carlos@empresa.mx',
  address: { city: 'Mérida', geo: { lat: '20.96', lng: '-89.62' } },
  company: null
};

// Lo que tu app necesita (estructura limpia)
function normalizarUsuario({ id, name, email, address, company }) {
  return {
    id,
    nombre: name,
    email: email.toLowerCase(),
    ciudad: address?.city ?? 'Sin ciudad',
    empresa: company?.name ?? 'Independiente',
    coordenadas: {
      lat: Number(address?.geo?.lat),
      lng: Number(address?.geo?.lng)
    }
  };
}

console.log(normalizarUsuario(apiUsuario));

Ejercicios ​

  1. Crea un objeto libro con título, autor, año y un método resumen() que devuelva "Cien años de soledad - Gabriel García Márquez (1967)".
  2. Dado const config = { tema: 'claro', idioma: 'es' }, crea una nueva configuración con tema: 'oscuro' y notificaciones: true sin modificar la original.
  3. Escribe una función saludar que reciba un objeto y use desestructuración con valor por defecto: saludar({ nombre: 'Ana' }) → "Hola, Ana"; saludar({}) → "Hola, invitado".
  4. Dado const inventario = { manzanas: 10, peras: 0, uvas: 25 }, obtén un array con los nombres de las frutas que sí tienen existencias.
  5. Quita la propiedad token de const sesion = { usuario: 'ana', token: 'abc', expira: 3600 } sin usar delete.
Ver solución
js
// 1
const libro = {
  titulo: 'Cien años de soledad',
  autor: 'Gabriel García Márquez',
  anio: 1967,
  resumen() {
    return `${this.titulo} - ${this.autor} (${this.anio})`;
  }
};

// 2
const config = { tema: 'claro', idioma: 'es' };
const nuevaConfig = { ...config, tema: 'oscuro', notificaciones: true };

// 3
function saludar({ nombre = 'invitado' } = {}) {
  return `Hola, ${nombre}`;
}

// 4
const inventario = { manzanas: 10, peras: 0, uvas: 25 };
const disponibles = Object.entries(inventario)
  .filter(([, cantidad]) => cantidad > 0)
  .map(([fruta]) => fruta); // ['manzanas', 'uvas']

// 5
const sesion = { usuario: 'ana', token: 'abc', expira: 3600 };
const { token, ...sesionSegura } = sesion;

Resumen ​

  • Un objeto agrupa datos relacionados en pares clave: valor; accedes con . o [].
  • Los métodos son funciones dentro del objeto; usa sintaxis de método (no flecha) si necesitas this.
  • Object.keys, values y entries te permiten recorrer y transformar objetos.
  • La desestructuración extrae valores; el spread copia y combina; el rest agrupa lo que sobra.
  • Los objetos se copian por referencia: usa spread para copias superficiales y structuredClone para profundas.
  • ?. y ?? te protegen de datos incompletos.

Siguiente: Strings y template literals

Academia Web — aprende, copia y construye.