1

Is this a bug in JavaScript object literals, at least the parser?

////////// a bug in JavaScript? //////////

// works:
const pointless = {
  "a b": 1,
  "c": 2
};

// works:
({
  "a b": 1,
  "c": 2
});

// fails when uncommented:
// {
//   "a b": 1,
//   "c": 2
// };

////////// what lead to the above //////////

// works:
class Thing {
  static get table() {
    return {
      'x': function () { console.log('You chose x!') },
      'y': function () { console.log('You chose y!') }
    };
  }
    
  static doAllTheThings(arg) {
    this.table[arg]();
  }
}

Thing.doAllTheThings('x');

// works:
function doAllTheThings(arg) {
  ({
    'x': function () { console.log('You chose x!') },
    'y': function () { console.log('You chose y!') }
  })[arg]();
}

doAllTheThings('y');

// fails when uncommented:
// function doAllTheThings(arg) {
//   {
//     'x': function () { console.log('You chose x!') },
//     'y': function () { console.log('You chose y!') }
//   }[arg]();
// }

// doAllTheThings('y');

Live demo at: https://repl.it/repls/DeadlyFatherlyVertex

I stumbled onto this trying to make a jump table instead of using a giant switch command. Wrapping the {} in () works but IMHO shouldn't be necessary.

Is there a reason it works this way?

Zack Morris
  • 4,727
  • 2
  • 55
  • 83
  • 10
    If `{` is seen at the beginning of a statement, it's treated as the beginning of a code block, not an object literal. – Barmar Apr 05 '18 at 20:12
  • Hey @Pointy, got a dupe for this one? I don't have it in my syntax dupe list. – Barmar Apr 05 '18 at 20:14
  • and - when it sees `(` first it simply validates that what is between `(` and `)` is a valid Javascript expression. So `({...})` doesn't do what you think it does. – Randy Casburn Apr 05 '18 at 20:14
  • There are certainly dupes out there; I can try but my SO search luck is pretty poor. – Pointy Apr 05 '18 at 20:14
  • Wow you guys are fast! 5 minutes from the time I asked to being marked as a duplicate :-) – Zack Morris Apr 05 '18 at 20:18

1 Answers1

1

When you use () to surround the {} you are creating an expression which is how the object gets evaluated.

However, you can also create an empty scope (still tied to the surrounding scope) in JavaScript by simply using {}, and as a result the interior of what you thought was an object actually gets interpreted as lines of code, failing at "a b" : 1, which is an invalid line of code.

{
    console.log(1);
}
Travis J
  • 81,153
  • 41
  • 202
  • 273