SyncroIT
SyncroIT

Reputation: 1578

Object destructuring into another object does not work

Today I had to merge two objects, picking the properties of an object a and placing them in an object b. I can't understand why the first syntax/statement is not working, while the second one is.

let user = { a: 1, b: 2 };
let data = { z: 1, c: 3, f: 8, d: 4 };

// Let's say I want user to be { a: 1, b: 2, c: 3}

// method 1 (not works) 
const r1 = {
    ...user,
    ...({c} = data)
};
document.getElementById("r1").innerText = JSON.stringify(r1);

// method 2 (works)
const r2 = {
    ...user,
    ...(({c}) => ({c}))(data)
};
document.getElementById("r2").innerText = JSON.stringify(r2);

You can try the code on https://jsfiddle.net/Ljb7ndp4/6/

Upvotes: 2

Views: 242

Answers (1)

Claudio Busatto
Claudio Busatto

Reputation: 761

In the second method you are creating an IIFE (Immediately Invoked Function Expression).

From MDN docs, "an IIFE (Immediately Invoked Function Expression) is a JavaScript function that runs as soon as it is defined". The IIFE on method 2 is returning an object like {c: <value>}. As objects support the spread operator, you are able to use it in the object definition.

To visualize it in your code, you can assign the result of the IIFE to a variable and print the result on console.

const val = (({c}) => ({c}))(data)
console.log(val) // { c: 3 }

The arrow function syntax, in this case, makes a little bit harder to visualize what is happening, but the code:

(({c}) => ({c}))(data);

is a short version of this one, which is better readable, in my opinion.

(function(arg) {
  return { c: arg.c }
})(data);

So, we can convert it to arrow function to understand all the transformations, step by step.

Initially we can convert the function to use the arrow function syntax:

((arg) => {
  return { c: arg: c }
})(data)

Then we can destructur c from the received argument.

(({c}) => {
  return { c: c }
})(data)

As the created arrow function does not require a block, we can simplify it:

// The parenthesis are added because the syntax () => {} is not valid.
(({c}) => ({ c: c }))(data)

And finally, we can use the short object syntax to make it exactly as the original one.

(({c}) => ({ c }))(data)

So, this function generates a { c: <value> } object, and therefore you can use the spread operator to merge it in the object you are building.

Upvotes: 3

Related Questions