Desestructuración y Spread
La desestructuración permite extraer valores de objetos y arrays en variables con una sintaxis compacta. El operador spread (...) los complementa para copiar y combinar estructuras. Juntos son ubicuos en JavaScript moderno.
Desestructuración de objetos
const usuario = { nombre: 'Ana', edad: 28, ciudad: 'Madrid' };
// Sin desestructuración
const nombre = usuario.nombre;
const edad = usuario.edad;
// Con desestructuración
const { nombre, edad } = usuario;
console.log(nombre); // 'Ana'
console.log(edad); // 28
// Renombrar al extraer
const { nombre: nombreUsuario, ciudad: localidad } = usuario;
console.log(nombreUsuario); // 'Ana'
console.log(localidad); // 'Madrid'
// Valor por defecto si la propiedad no existe
const { nombre, rol = 'lector' } = usuario;
console.log(rol); // 'lector' — la propiedad no existía en el objeto
Desestructuración de arrays
const colores = ['rojo', 'verde', 'azul'];
const [primero, segundo] = colores;
console.log(primero); // 'rojo'
console.log(segundo); // 'verde'
// Saltar elementos
const [, , tercero] = colores;
console.log(tercero); // 'azul'
// Intercambiar variables sin temporal
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b); // 2 1
Rest en desestructuración
El operador ...rest recoge lo que no se extrajo. Solo puede ir al final:
// En objetos
const { nombre, ...resto } = usuario;
console.log(nombre); // 'Ana'
console.log(resto); // { edad: 28, ciudad: 'Madrid' }
// En arrays
const [primero, ...losOtros] = [1, 2, 3, 4, 5];
console.log(primero); // 1
console.log(losOtros); // [2, 3, 4, 5]
Desestructuración anidada
const config = {
servidor: {
host: 'localhost',
puerto: 3000,
},
bd: {
nombre: 'miapp',
usuario: 'admin',
},
};
// Extraer propiedades profundas
const { servidor: { host, puerto }, bd: { nombre: bdNombre } } = config;
console.log(host); // 'localhost'
console.log(puerto); // 3000
console.log(bdNombre); // 'miapp'
Desestructuración en parámetros de función
Es el uso más frecuente en frontend moderno:
// Sin desestructuración
function mostrarUsuario(usuario) {
console.log(usuario.nombre, usuario.email);
}
// Con desestructuración en el parámetro
function mostrarUsuario({ nombre, email }) {
console.log(nombre, email);
}
// Con valor por defecto en los parámetros
function crearElemento({ tag = 'div', clase = '', texto = '' } = {}) {
const el = document.createElement(tag);
el.className = clase;
el.textContent = texto;
return el;
}
// = {} al final hace que la función funcione sin argumento
crearElemento(); // div vacío
crearElemento({ tag: 'p', texto: 'Hola' }); // <p>Hola</p>
Spread en objetos
Copia y combina propiedades:
const base = { color: 'rojo', tamaño: 'M' };
const extra = { precio: 10, stock: 5 };
// Combinar objetos
const producto = { ...base, ...extra };
// { color: 'rojo', tamaño: 'M', precio: 10, stock: 5 }
// Copiar con modificación (la propiedad más a la derecha gana)
const actualizado = { ...base, color: 'azul' };
// { color: 'azul', tamaño: 'M' }
// Actualizar estado de forma inmutable (patrón React/Redux)
const estado = { usuario: 'Ana', paginaActual: 1, cargando: false };
const nuevoEstado = { ...estado, paginaActual: 2 };
El spread es superficial (shallow copy). Las propiedades anidadas siguen siendo referencias compartidas.
const obj = { a: 1, nested: { b: 2 } };
const copia = { ...obj };
copia.a = 99; // no afecta al original
copia.nested.b = 99; // ← SÍ afecta al original (referencia compartida)
Spread en arrays
const nums = [1, 2, 3];
// Copiar un array
const copia = [...nums];
// Combinar arrays
const mas = [...nums, 4, 5, 6];
// [1, 2, 3, 4, 5, 6]
const combinado = [...[1, 2], ...[3, 4], 5];
// [1, 2, 3, 4, 5]
// Pasar array como argumentos
const maxValor = Math.max(...nums); // equivale a Math.max(1, 2, 3)
Desestructuración con iterables
La desestructuración de array funciona con cualquier iterable: strings, Maps, Sets, resultados de generators:
const [primera, segunda] = 'Hola';
console.log(primera); // 'H'
console.log(segunda); // 'o'
const [clave, valor] = new Map([['nombre', 'Ana']]).entries().next().value;
// Muy útil con Object.entries
const precios = { manzana: 1.2, pera: 0.8 };
for (const [fruta, precio] of Object.entries(precios)) {
console.log(`${fruta}: ${precio}€`);
}
En la siguiente lección entramos en uno de los conceptos más profundos de JavaScript: closures y scope.