Why does chrome console gives a different result between {} + {} and {} + {};

Viewed 229

If I type in Chrome console

{} + {} I get "[object Object][object Object]"

but if I add a semicolon the result is different:

{} + {}; I get NaN

I don't understand the difference though. First one makes sense, to me as the addition operator rules are the following:

  1. If at least one operand is an object, it is converted to a primitive value (string, number or boolean);
  2. After conversion, if at least one operand is string type, the second operand is converted to string and the concatenation is executed;
  3. In other case both operands are converted to numbers and arithmetic addition is executed.

Since both operands are object, they are converted to string. But what is going on in the second case?

If I assign a value (a = ...) in both cases my variable will be a string. I tried to look for a specification of what Chrome console return when an expression is given, but didn't find one. Weirdly enough adding a comment will return NaN too : {} + {} //comment => NaN

I know Javascript can be strange sometimes, but there is almost always a logical explanation. Here it seems to depend on how Chrome interprets it. Firefox on the other hand returns NaN for both cases, which I don't understand either.

1 Answers

I believe the difference lies in how the Chrome Console interprets your code:

This is an expression:

{} + {}
//=> "[object Object][object Object]"

And this is a "program":

{} + {};

Note that NaN can be achieved with just {} + {} if that was your "full program":

enter image description here

Here's what Dr. Axel Rauschmayer says in "What is {} + {} in JavaScript?"

The problem is that JavaScript interprets the first {} as an empty code block and ignores it. The NaN is therefore computed by evaluating +{} (plus followed by the second {}).

So in {} + {};, the NaN comes from evaluating +{}. (The first {} is ignored.)

The first {} as a code block is more obvious with this example: (try this in your command line)

{ while (false) x++ } + {}
//=> NaN

If JS was to see { while (false) x++ } as an object, it would throw a syntax error. But it doesn't, in this case it has to be a code block; it ignores it and evaluates +{} yielding NaN.

So to "force" JS to see {} as objects and not code blocks, you can wrap them in (). Try this in your Chrome Console:

({}) + ({});
//=> "[object Object][object Object]"

({} + {});
//=> "[object Object][object Object]"
Related