-2

Imagine this scenario where I keep my field name in a variable like this -

const NAME_FIELD = 'name';

Then, I go ahead and use this inside an object like this -

let state = {
  [NAME_FIELD]: 'ashwani'
} 
console.log(state) // Output - { name: "ashwani" }

All good till now. Now, later in my code, I want to get value of this same key. Ofcourse the easy way out is to simply use something like state[NAME_FIELD]. I am using destructuring though.

With destructuring, this works -

const { [NAME_FIELD]: x } = state;
console.log(x) // Output - ashwani

But, my first attempt to this was like this -

const { name } = state; // This works as expected
const { [NAME_FIELD] } = state; // I was expecting this to work too, but it didn't

I expected the above code const { [NAME_FIELD] } = state; to work but it didn't while the other ones worked. Will be really great if someone can help me understand that :)

I know that JS throws a parse error when I say const { [NAME_FIELD] } = state;. With my question, I am trying to understand why ECMAScript team would have made this decision and what is it I am missing in my understanding. In the later comments, some of SO members have provided certain useful views on this.

thisisashwani
  • 1,748
  • 2
  • 18
  • 25
  • 1
    also in that last example, your code won't even run, it generates a parse error, and then tells you that you forgot `:` – Mike 'Pomax' Kamermans Jul 01 '21 at 07:49
  • So is your question "why does `a="test"; b = { a }` work, and `b = { [a]: "test" }` work, but `b = { [a] }` does not?" – Mike 'Pomax' Kamermans Jul 01 '21 at 07:52
  • 2
    If you want to really know what happens "behind the scenes" - read the [spec](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-destructuring-assignment) – Jaromanda X Jul 01 '21 at 07:52
  • @Mike'Pomax'Kamermans, this would have worked, right? - const { name } = state; Same way, I expect the other code to work too :) – thisisashwani Jul 01 '21 at 07:53
  • 2
    @thisisashwani If you expect something sensible from the syntax `const { [NAME_FIELD] } = state;`, then be aware that you can create a [TC39 proposal](//github.com/tc39/proposals/). If you expect `const { [NAME_FIELD] } = state;` to behave just like `const { name } = state;` because `NAME_FIELD === "name"`, then this feels too much like a syntax ambiguity when compared to array destructuring. Should `const [ x ] = [ 0 ];` set `x = 0` or should it read the variable name `x`? – Sebastian Simon Jul 01 '21 at 07:54
  • By the way, I have zero idea why my question is getting downvotes when it's not even a duplicate :) By the way, thanks for the info, @SebastianSimon – thisisashwani Jul 01 '21 at 07:57
  • Your point makes sense, @SebastianSimon. It's ambiguous, that's why I properly put up this question. Will be great if you can put your point as an answer. Can gladly upvote that :) – thisisashwani Jul 01 '21 at 08:02
  • Thanks, @JaromandaX. That's way more helpful compared to the other initial comments and the downvotes :) – thisisashwani Jul 01 '21 at 08:03
  • 3
    if `const { [NAME_FIELD] } = state;` were to work, then what would happen to strings that aren't valid identifiers, such as `NAME_FIELD = "1abc"` or `NAME_FIELD = "name with spaces"`? enforcing an alias ensures you have a valid identifier/variable name – Nick Parsons Jul 01 '21 at 08:12
  • Oh, true @NickParsons. I never thought that way. That's a very valid point. Now that makes sense why JS team would have decided for this piece of code to not work. Will be great if you can put this up as an answer :) – thisisashwani Jul 01 '21 at 08:14
  • 2
    I'm not sure why this would be useful even if it were allowed. Presumably you would like `const { [NAME_FIELD] } = state` to declare a constant called `name` (since "name" is the value of `NAME_FIELD`) and assign it to the corresponding property in the `state` object. But there is no way in Javascript to access a "variable variable" - so you'd have to know that the property name is specifically `name`, in which case there's no difference from just doing `const { name } = state`. (Concluded in next comment.) – Robin Zigmond Jul 03 '21 at 13:25
  • 1
    Ironically you only keep the benefit of using a const rather than a hardcoded string by referring to the object property: `state[NAME_FIELD]` works, but there is no equivalent for a local variable. – Robin Zigmond Jul 03 '21 at 13:25
  • True, @RobinZigmond. `state[NAME_FIELD]` works because `NAME_FIELD` translates to 'name', and I can definitely go ahead and simply use this. When I wrote this question, I was just interested to know why the other one doesn't work :) Such computed property names are useful when I want one common config file for the fields (which are used for state, error validation mapping and other similar things for a single component) so that over time, people don't end up changing one piece of codebase to end up breaking other things, and then spending their time debugging the issue :) – thisisashwani Jul 04 '21 at 04:47

3 Answers3

6

One of the issues with the syntax of:

const { [NAME_FIELD] } = state;

... is that it assumes that the value held in NAME_FIELD is a valid identifier which is not always the case. In the case of NAME_FIELD = "name", name is a valid identifier, so it's easy to assume that NAME_FIELD can be made into a valid variable, however, this is not always the case. Consider if you had:

const NAME_FIELD = "my-key";
const { [NAME_FIELD] } = state; // which would be interpreted as { my-key }

this wouldn't work as it would mean creating a variable with a hyphen -, which isn't valid. Similar issues occur with other valid object keys that aren't considered valid identifiers, such as "123", "my key", and symbols.

As a result, an alias needs to be used to assign the destructured value to a valid identifier.

Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
3
const { [NAME_FIELD] } = state;
console.log(x) // I was expecting it to print my name, but it didn't

this doesn't work because why would javascript log the name when you try to log the value of a variable that's not defined

const { [NAME_FIELD]: x } = state;
console.log(x) // Output - ashwani

this works because when you use : x you're asking javascript to rename the destructured prop to 'x'

Edit:

const { [NAME_FIELD] } = state;
// I was expecting the above code to work too, but it didn't

this won't work because it is invalid syntax, and what variable would javascript use in this case as you're destructuring using a dynamic key?

Ramesh Reddy
  • 10,159
  • 3
  • 17
  • 32
  • I have edited my question. My basic question is const { [NAME_FIELD] } = state; throws an error :) – thisisashwani Jul 01 '21 at 07:49
  • Thanks, @Ramesh. I guess it's because of the ambiguity. Since const { name } = state; works, I expected const { [NAME_FIELD] } = state; to work too. – thisisashwani Jul 01 '21 at 08:06
1

The reason behind avoiding this functionality is because it would bring in dynamically named variables into a blocked scope. Which is extremely dangerous. It has been removed from ES5 strict mode.

Javascript MDN suggests not to use dynamic eval. You may end up running malicious code.

You can refer to @Ginden's answer here.

Ashwin R
  • 744
  • 7
  • 14