Desestructuración en ES6. Parte II: objetos

Cosmic Thing, Damián Ortega, 2002
Photo: Agostino Osio/hangarbicocca.org

No sé si estarás de acuerdo, pero desestructurar arrays ha resultado más sencillo de lo que el nombre parece indicar. No va a ser muy diferente con los objetos.

Siguiendo con nuestra metáfora de una API que devuelve los datos en un formato que queremos reestructurar, supongamos ahora que me devuelve un objeto con propiedades a, b y c, cuyos valores quiero reasignar a las variables x, y y z :

function uglyAPI() { 
	return { a: 1, b: 2, c: 3 }; 
}

var { 
    a: x, 
    b: y,
    c: z } = uglyAPI();

console.log( x, y, z );   //  1 2 3 

Un momento, esto es un poco raro. Sí, lo es, efectivamente la variable a la que quiero asignar el valor se pone a la derecha de los :. Este es el único obstáculo mental a vencer con la desestructuración de objetos.

La forma de acordarse de que hay que escribir la asignación al revés de lo que dicta la intuición es acordarse de que el nombre de la propiedad siempre se escribe a la izquierda.

x, y y z son nombres de variables, a, b y c son nombres de propiedades del objeto que queremos desestructurar.

Si ahora te acuerdas de como, en el capítulo anterior, podíamos asignar valores de un array a variables concretas usando los índices del array, verás que la sintaxis marciana que usábamos entonces cobra más sentido ahora:

function uglyAPI() { return [21, 22, 23, 24, 25, 26, 27, 28]; }

var {
    1: a, 
    5: b, 
    6: c } = uglyAPI();

console.log(a, b, c); // 22 26 27

De todos modos, con los objetos, es habitual reutilizar los nombres de las propiedades como nombres de las nuevas variables, de forma que:

function uglyAPI() { 
	return { a: 1, b: 2, c: 3 }; 
}

var { 
    a: a, 
    b: b,
    c: c } = uglyAPI();

console.log( a, b, c );   //  1 2 3 

Puede escribirse y suele escribirse, para comodidad de nuestras neuronas, así:

function uglyAPI() { 
	return { a: 1, b: 2, c: 3 }; 
}

var { a, b, c } = uglyAPI();

En este caso, lo escribo en una sola línea por comodidad, y porque no hay problema con la legibilidad, al ser sólo tres variables.

Esto es una mejora más que considerable respecto de como se desestructuraban objetos antes de ES6; no porque sean menos líneas, sino porque implica menos carga mental escribirlo sin equivocarse y leerlo sin perderse:

function uglyAPI() { 
	return { a: 1, b: 2, c: 3 }; 
}
var tmp = uglyAPI(),
	a = tmp.a, 
    b = tmp.b,
    c = tmp.c;

De nuevo, como con los arrays, no es necesario usar todas las propiedades:

function uglyAPI() { 
	return { a: 1, b: 2, c: 3 }; 
}

var { a } = uglyAPI();

console.log( a );   //  1

Y, una vez más y antes de que me olvide, si queremos evitar sorpresas desagradables, conviene que usemos el operador cortocircuito OR para que Javascript no lance un error si la API no devuelve nada o devuelve un objeto nulo:

function uglyAPI() { 
	return { a: 1, b: 2, c: 3 }; 
}

var { a, b, c } = uglyAPI() || {};

Si intentamos asignar una variable que no existe como propiedad en el objeto, esa variable acabará teniendo un valor undefined:

function uglyAPI() { 
	return { a: 1, b: 2, c: 3 }; 
}

var { a, b, c, d } = uglyAPI();
console.log( a, b, c, d );   //  1 2 3 undefined

Pero una vez más, como con los arrays, podemos hacer uso de valores por defecto, en caso de que la propiedad no esté definida:

function uglyAPI() { 
	return { a: 1, b: 2, c: 3 }; 
}

var { 
    a = 50, 
    b = 13, 
    d = 42 } = uglyAPI();

console.log( a, b, d );   //  1 2 42 undefined

Y si queremos rizar el rizo y cambiar el nombre de la variable y además proporcionar un valor por defecto, podemos hacer lo siguiente:

function uglyAPI() { 
	return { a: 1, b: 2, c: 3 }; 
}

var { 
    a: x = 50, 
    b = 13, 
    d: w = 42 } = uglyAPI();

console.log( x, b, w );   //  1 2 42 undefined

También podemos desestructurar objetos anidados:

function uglyAPI() { 
	return { a: 1, b: 2, c: { d: 3 }, e: 4 }; 
}

var { a,  b, c: { d }, e } = uglyAPI();
console.log( a, b, d, e);   //  1 2 3 4

Te dejo que hagas una pausa para evitar que te explote el cerebro…

Si lo piensas con cuidado, asumiendo lo que hemos visto antes cuando queremos renombrar las propiedades, verás que tiene sentido.

Ahora, hemos discutido la desestructuración de arrays y objetos en el contexto de una API que nos devuelve los datos en un formato que nos es incómodo o no nos gusta.

Puede que te haya pasado o puede que no. A mi me ha pasado unas cuantas veces, y recuerdo con especial dolor una de las primeras librerías de física para videojuegos que use, hace ya años, que en lugar de usar las coordenadas de los objetos de juego como variables o propiedades x, e y, usaba arrays en el formato [x, y].

La nueva sintaxis para desestructuración de ES6 resuelve este tipo de incordio elegantemente. Pero hace mucho más y hablaré de ello en la siguiente entrega.

Pero mientras te dejo algunos ejemplos-ejercicio, para mantenerte entretenida.

Intenta adivinar que va a ocurrir cuando ejecutes los siguientes códigos:

  1. function showListValues( [a, b, c] ) {
        console.log(a, b, c);
    }
    showListValues([1, 2, 3]);
    
  2. function showObjectValues( {a, b, c} ) {
        console.log(a, b, c);
    }
    showObjectValues( { a: 1, b: 2, c:3 });
    
  3. function showListValues( [a, b, c] ) {
        console.log(a, b, c);
    }
    showListValues();
    

    ¿Cómo evitarías el problema?

  4. function showObjectValues( {a, b, c} ) {
        console.log(a, b, c);
    }
    showObjectValues();
    

    ¿Cómo evitarías el problema?

  5. function showListValues( [a, b, c] ) {
        console.log(a, b, c);
    }
    showListValues([1, 2]);
    

    ¿Cómo evitarías el valor indefinido en c?

  6. function showObjectValues( {a, b, c} ) {
        console.log(a, b, c);
    }
    showObjectValues({ a: 1, c:3 });
    

    ¿Cómo evitarías el valor indefinido en b?


ACTUALIZACIONES:

18/08/2019: Corregida errata en la mayoría de ejemplos. Por equivocación el objeto que devolvía uglyAPI era { a: 1, b: 2, b: 3 } en lugar de { a: 1, b: 2, c: 3 }

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.