2

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.

Ricola
  • 2,621
  • 12
  • 22
  • 1
    "... there is almost always a logical explanation" Depending on how you define "logical". There's always a *consistent* explanation, even if that consistency is localized to a specific implementation. – Dave Newton May 25 '20 at 20:27
  • 1
    You can simplify your focus by ignoring anything to do with the `+` operator. You can reproduce a simpler case with the difference between `{}` and `{};`, where `{};` produces `undefined`. So your `+` case is likely being treated as `{} + undefined`, thus `NaN`. Not a full explanation, but at least you know you can rule out `+` as the cause. – Chase May 25 '20 at 20:31
  • @Chase See https://2ality.com/2012/01/object-plus-object.html – customcommander May 25 '20 at 20:53

1 Answers1

3

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]"
customcommander
  • 17,580
  • 5
  • 58
  • 84
  • Why `{} +1` and `({} +1)` do not return the same value then? First case should return a string also as it is an expression. – Ricola May 26 '20 at 14:23
  • 1
    @Ricola I _think_ it's because in `{} + 1` the object is seen as a code block and is ignored yielding `1`. In the second example, since you can't have a code block in parens, it has to be an object. It is therefore casted into a string and prepended to "1". In `{} + {}`, the engine _may_ come to the conclusion that concatenating two code blocks make no sense and therefore threat the two things as objects. – customcommander May 26 '20 at 14:42
  • Do you know if there is any specifications on what the Chrome console returns? For example, how do you know that one is treated as an expression and another one as a "program"? – Ricola May 26 '20 at 16:14
  • 1
    @Ricola I don't know. However I do know that an expression is something that you can pass around. e.g. `10 + 10` is an expression. You can assign it to a variable or pass it to a function _as is_. Whereas `var x = 10 + 10;` is a statement; you can't do `foo(var x = 10 + 10)`. The `;` is used to separate statements so the Chrome console must somehow make that call if that makes sense. – customcommander May 26 '20 at 20:03
  • thank you for your answers. I was a bit hoping that somebody could come up with completely rational explanations but I guess since there is no specification of the console then it would simply depend on the implementation, so it only leaves us with speculation. – Ricola May 31 '20 at 18:52