42

Possible Duplicate:
What is the explanation for these bizarre JavaScript behaviours mentioned in the 'Wat' talk for CodeMash 2012?

I know that when [] is coerced to a string it returns the empty string (""), and when {} is coerced to a string it returns "[object Object]".

When I run [] + {} in my browser's Javascript console, it returns as I would expect:

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

But when I run {} + [], it returns a completely unexpected value:

>> {} + []
0

What could be causing it to return 0?

Community
  • 1
  • 1
Daniel
  • 47,404
  • 11
  • 101
  • 179
  • Looks like you are adding null to null. This would be equivalent to 0 + 0. That is just a guess though. – Trisped Aug 13 '12 at 17:12
  • 4
    @Trisped: Neither of those are null. – SLaks Aug 13 '12 at 17:13
  • 2
    This question is subsumed by http://stackoverflow.com/questions/9032856/what-is-the-explanation-for-these-bizarre-javascript-behaviours-mentioned-in-the (which as of now has 301 votes)..... – Ray Toal Aug 13 '12 at 19:39
  • 2
    has someone been watching "Wat" by destroyallsoftware? :P – ardent Aug 13 '12 at 19:56

3 Answers3

68

When there is a { at the beginning of a statement, it will be interpreted as a block, which may contain zero or more statements. An block with no statements in it will have an empty continuation value.

In other words, in this case, {} is interpreted as an empty code block.

The statement ends after the ending brace }, which means that the next three characters +[] comprise a statement of their own.

At the beginning of an expression or statement, + is the unary plus operator, which coerces its operand to a number.

So +[] is the same as Number([]), which evaluates to 0.

In short, {} + [] is an empty code block followed by an array coerced to a number.


All that said, if you evaluate {} + [] inside an expression, it will return what you expect:

>> ({} + []) 
"[object Object]" 

Another interesting thing is that you cannot begin a statement with an object literal because the interpreter will try to parse it as a statement. Doing this

{ "object": "literal" };

will throw a syntax error.

Peter Olson
  • 139,199
  • 49
  • 202
  • 242
  • 4
    Interestingly, an object literal with a single property is not a syntax error at the beginning of a statement if you leave off the quotes on the property name. It just doesn't mean what it looks like it does. For example, `{ object: "literal" }` is interpreted as a block statement with a single statement, `"literal"`. `object` becomes a label for the statement. – Matthew Crumley Aug 13 '12 at 17:53
  • @MatthewCrumley That is because `object:` is treated as a label (the ones you can use with break statements) – Ruan Mendes Aug 14 '12 at 23:30
  • @Peter Olson. I appreciate your response. However, the expression `{ "object": "literal" };` will only throw an error in firefox. Chrome treats it as an object literal. – Cels Jun 27 '20 at 19:31
20

Because the {} is treated as a block. Thus your statement is actually:

{

//empty block here
}

+[] //0 same as Number([])

This is why this is invalid javascript:

eval('{hello: "world", key: "value"}') //Syntax error

You can add () to make it an expression (blocks cannot be used in an expression so it will be object initializer:

eval('({hello: "world", key: "value"})') //Object
Esailija
  • 138,174
  • 23
  • 272
  • 326
  • 2
    It's not immediately obvious to me what is wrong with this answer, so please explain the downvote. – Esailija Aug 13 '12 at 17:33
  • 2
    +1 to offset downvote.. You were about 25 seconds earlier, and I think your multi-line example is much clearer – Izkata Aug 13 '12 at 19:07
2

The empty block gets coerced into a zero. Then the + operator decides to coerce the [] to a number.

Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • 1
    The empty block is an empty block, it's not coerced to anything. – alex Aug 14 '12 at 01:07
  • 1
    @alex, you are correct, after reading Peter Olsen's answer, I understand that the only coercion is of the Array into a number and the first set of brackets is just ignored, the last statement is returned – Ruan Mendes Aug 14 '12 at 23:32