2

Why can I not set a key in a newly created object like this:

const baseObject = {key: "a", val: "b"}
const modifiedObject = {baseObject.val: baseObject.key} // SyntaxError: Unexpected token '.'

But instead using brackets is ok:

const modifiedObject = {[baseObject.val]: baseObject.key} // OK

From my understanding [baseObject.val] should create a new array from the baseObject.val with only that item in it. Can you explain why this works? Is this the best practice approach on setting a key from an object's nested property?

I tried finding information on MDN and other sources but could not find any. I assume my search phrases are wrong since there should be a pretty basic explanation. Feel free to mark as duplicate if you can link me to already provided answers.

Christopher Graf
  • 1,929
  • 1
  • 17
  • 34
  • 2
    Also see [*How to use a variable for a key in a JavaScript object literal?*](https://stackoverflow.com/questions/2274242/how-to-use-a-variable-for-a-key-in-a-javascript-object-literal) and [*Creating object with dynamic keys*](https://stackoverflow.com/questions/19837916/creating-object-with-dynamic-keys). – RobG Apr 24 '20 at 10:16

2 Answers2

6

What you have with [baseObject.val] is not an array, but a "computed property name", a special syntax for object literals.

What it does is, when inside an object literal where a key should be, it evaluates the expression inside the brackets and then defines a property on the object being constructed with that expression. For example, { ['foo']: 'bar' } results in { foo: 'bar' }. { ['a' + 'b']: 'bar' } results in { ab: 'bar' }.

You can put any expression you want inside the [] brackets, and the result will be the key put on the object. For your case, you want the expression value of baseObject.val, so the syntax is [baseObject.val]:.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Can you also explain why the notation without brackets is not allowed in JavaScript? I don't see the reason why... – Christopher Graf Apr 24 '20 at 10:19
  • 1
    I would guess that it's because otherwise, the interpreter would have to dynamically determine whether what was referenced was an expression or was meant to be a plain string property, eg `const foo = 'abc'; const obj = { foo: 'val' }`. Would the object be `{ foo: 'val' }` or `{ abc: 'val' }`? Rules could be made to determine it, but it'd be confusing for script-writers and would complicate the grammar. – CertainPerformance Apr 24 '20 at 10:22
1

[ and ] are punctuators that have a different meaning in different contexts. Depending on where they appear, they might signify an array literal:

let a = [];

or delimit a property name (aka "square bracket notation") where an expression is to be evaluated to get the property name:

let foo = 'log';
console[foo]('foo'); // equivalent to console.log('foo');

or define assignment of array values to variables:

let [a, b, c] = [1, 2, 3]

In the context of the OP, they delimit a computed property name, similar to the second example above:

let x = 'foo';
let obj= {[x] : 'Foo'};

which creates an object as if by:

let obj = {foo: 'Foo'}; 
RobG
  • 142,382
  • 31
  • 172
  • 209