Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to destructure into dynamically named variables in ES6?

Let's suppose I have the following object:

const user = { 
  id: 42, 
  displayName: "jdoe",
  fullName: { 
      firstName: "John",
      lastName: "Doe"
  }
};

And that I want only the id and fullName.

I will do the following :

const { id, fullName } = user

Easy-peasy, right?

Now let's suppose that I want to do the destructuring based on the value of another variable called fields.

const fields = [ 'id', 'fullName' ]

Now my question is : How can I do destructuring based on an array of keys?

I shamelessly tried the following without success:

let {[{...fields}]} = user and let {[...fields]} = user. Is there any way that this could be done?

Thank you

like image 807
Anas Avatar asked Mar 11 '16 11:03

Anas


People also ask

How do you Destructure an object in ES6?

When destructuring the objects, we use keys as the name of the variable. The variable name must match the property (or keys) name of the object. If it does not match, then it receives an undefined value. This is how JavaScript knows which property of the object we want to assign.

Can we Destructure array in JavaScript?

To destructure an array in JavaScript, we use the square brackets [] to store the variable name which will be assigned to the name of the array storing the element.

Can you Destructure nested object?

Nested Object and Array Destructuring Here's another example with an array of objects: You can destructure as deeply as you like: As you can see, keys a , b , and c are not implicitly defined, even though we pulled out nested values, firstElemOfC and remainingElementsOfC , from the array at c .


Video Answer


3 Answers

It's not impossible to destructure with a dynamic key. To prevent the problem of creating dynamic variables (as Ginden mentioned) you need to provide aliases.

const user = { 
  id: 42, 
  displayName: "jdoe",
  fullName: { 
      firstName: "John",
      lastName: "Doe"
  }
};

const fields = [ 'id', 'fullName' ];
const object = {};

const {[fields[0]]: id, [fields[1]]: fullName} = user;

console.log(id); // 42
console.log(fullName); // { firstName: "John", lastName: "Doe" }

To get around the problem of having to define static aliases for dynamic values, you can assign to an object's dynamic properties. In this simple example, this is the same as reverting the whole destructuring, though :)

const user = { 
  id: 42, 
  displayName: "jdoe",
  fullName: { 
      firstName: "John",
      lastName: "Doe"
  }
};

const fields = [ 'id', 'fullName' ];
const object = {};

({[fields[0]]: object[fields[0]], [fields[1]]: object[fields[1]]} = user);

console.log(object.id); // 42
console.log(object.fullName); // { firstName: "John", lastName: "Doe" }

sources:

  • https://twitter.com/ydkjs/status/699845396084846592

  • https://github.com/getify/You-Dont-Know-JS/blob/master/es6%20%26%20beyond/ch2.md#not-just-declarations

like image 60
Paul Kögel Avatar answered Oct 26 '22 21:10

Paul Kögel


Short answer: it's impossible and it won't be possible.

Reasoning behind this: it would introduce new dynamically named variables into block scope, effectively being dynamic eval, thus disabling any performance optimization. Dynamic eval that can modify scope in fly was always regarded as extremely dangerous and was removed from ES5 strict mode.

Moreover, it would be a code smell - referencing undefined variables throws ReferenceError, so you would need more boilerplate code to safely handle such dynamic scope.

like image 26
Ginden Avatar answered Oct 26 '22 22:10

Ginden


Paul Kögel's answer is great, but I wanted to give a simpler example for when you need only the value of a dynamic field but don't need to assign it to a dynamic key.

let obj = {x: 3, y: 6};
let dynamicField = 'x';

let {[dynamicField]: value} = obj;

console.log(value);
like image 30
junvar Avatar answered Oct 26 '22 22:10

junvar