Nate Lipp
Nate Lipp

Reputation: 810

Why does a semicolon affect object initialization in es6?

The only difference in the following code is a the semicolon.

Can anyone tell me why is the result different?

key = 'value'    // "value"
{key}         // {key: "value"}
{key};        // semicolon is only diff,    "value"

Upvotes: 2

Views: 367

Answers (2)

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276496

This is actually not related to JavaScript or browsers but specifically how the Chrome DevTools parses expressions. If you run your code in a regular script you will not run into this behavior. I run into a bit of why in this answer.

Here is what's happening:

key = 'value'    // "value"

this defines a variable (on the global scope in non-strict mode) and assigns it a value.

 {key}         // {key: "value"}

This is a block, the Chrome devtools sees this this and wraps the object. It runs a regular expression against your code and checks specifically if it looks like an object literal:

try {
  // Check if the code can be interpreted as an expression.
  parse('return ' + code + ';');

  // No syntax error! Does it work parenthesized?
  const wrappedCode = '(' + code + ')';
  parse(wrappedCode);

  return wrappedCode;
} catch (e) {
  return code;
}

Which it can be interpreted as so {key} is converted to a ({key}) which is an object literal and works.

{key};        // semicolon is only diff,    "value"

This on the other hand has a semicolon at the end, since the above code converts it to ({key};) which is invalid JavaScript the pre-processing code in the Chrome devtools enters the catch clause and returns the original code.

This is a statement and not an expression. Essentially parsed like:

{
  key;
}

In JavaScript, every statement has a "secret" value and you are simply seeing the log result of the last value of the script the REPL is giving you - in this case the string.

Upvotes: 2

Chris Baker
Chris Baker

Reputation: 50612

Our testing around the office shows this to be a quirk of the console. If you try to use this construct, with or without the semicolon, in a script, or eval it, or assign it to a variable, all result in the object {key: "value"} in browsers that support object initializers.

Testing in Chrome, we see results like yours. In Firefox, it produces an object regardless of the semicolon. In IE, it outputs the string whether you have the semicolon at the end or not.

It's also worth noting that creating an object with this notation, {key} to produce {key: "value"}, doesn't work in IE. In Chrome and Firefox, the browser will infer your meaning and produce the object with object initilizers (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#New_notations_in_ECMAScript_2015), IE will ask you what you're doing with your life because it does not support them.

You can create a similar situation with the script below, which will operate in console and give you surprising results, but isn't valid in a script. Just try to anticipate what this will output in console!

key1 = 'key';
key2 = 'key2';
{ {key1, key2} }

Long story short, though, don't depend on this behavior in a real script. Define your objects using standard notation (or object initializers if you're polyfilled for IE).

Upvotes: 0

Related Questions