6

When I type simple objects to Chrome JavaScript Console, I get an output like this:

>true
true
>1/3
0.3333333333333333

And so on.

But a syntax error occurs when I type objects:

>{ a: 1, b: 2 }
SyntaxError: Unexpected token :
arguments: Array[1]
0: ":"
length: 1
__proto__: Array[0]
get message: function getter() { [native code] }
get stack: function getter() { [native code] }
set message: function setter() { [native code] }
set stack: function setter() { [native code] }
type: "unexpected_token"
__proto__: Error

While I know for sure that this expression could be correctly used in initializing an object, because:

>obj = { a: 1, b: 2 }
Object
a: 1
b: 2
__proto__: Object

Maybe it's a silly question, but I really want to know the reason why is this happening?

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
Sergey
  • 47,222
  • 25
  • 87
  • 129
  • 3
    I know enough to tell you that this is because JavaScript is very particular about what is a valid expression and what is not. For example, `function foo(){}` is a _Function Declaration_ but `(function foo(){})` is a _Function Expression_ due to the syntax rules, and they have different functional implications. I don't know the spec enough to point you to the exact wording that disallows `{}` as an expression but allows `({})` (try it!), but I do know the spec's insanity enough to tell you that that answer will likely just make you say "Huh. OK.". – Phrogz Jan 31 '12 at 15:30
  • The best answer you're likely to get is similar to the _reason_ that `+[]` equals `0`, but `+[]+[]` equals the string `"0"`. The reason is _"because that's what the spec says to do"_, without any great insight into _why_ the spec authors chose to make that decision. – Phrogz Jan 31 '12 at 15:33
  • Interestingly, typing just `{a:1}` results in `1`, again due to a different interpretation of what that happens to be. A great answer might also include why this is the case. An epic answer would show what confusion/conflict might occur if this expression were interpreted as we expect. – Phrogz Jan 31 '12 at 15:35
  • I can't reproduce this problem unless I add an index after the object, as in https://stackoverflow.com/questions/48548444/javascript-grammar-indexing-object-literals-syntactically-forbidden#48548476 Has the console parser changed since 2012? – Barmar Jan 31 '18 at 18:04
  • Yes, it's changed: https://stackoverflow.com/a/36438289/864233 – Barmar Jan 31 '18 at 18:09

6 Answers6

8

Because your statement is being evaluated as a block, not an object literal declaration.

Note that an ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block. Also, an ExpressionStatement cannot start with the function keyword because that might make it ambiguous with a FunctionDeclaration.

To make it evaluate as an expression, it needs to be the right-hand side of an assignment, wrapped in parentheses or preceded by an operator. (!{a:1,b:2})

josh3736
  • 139,160
  • 33
  • 216
  • 263
  • `!{a:1}` doesn't really help when you want the value though ;) – Ry- Jan 31 '12 at 15:37
  • 1
    @minitech: Nope, but it does force expression evaluation. As a practical application, you can use that property to shave a byte off of self-executing functions: `!function(){...}();` instead of the traditional `(function(){...})();` – josh3736 Jan 31 '12 at 15:40
7
 { a: 1, b: 2 }

is a code block, with two wrongly labelled variables.

To create an object, surround the code block by parentheses, so that the braces are interpreted as object literals:

({ a: 1, b: 2 })
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • Interestingly enough, labelled variables work. It's the comma that's the problem, and if you change it to a semicolon it works too. Strange. You can embed URLs in JavaScript too then... – Ry- Jan 31 '12 at 15:39
4

It's because an opening { with no context is interpreted as the beginning of a block. You can use parentheses:

({ a: 1, b: 2 })

As it is though, it's just a block of execution - like one might find after an if or for. So you can type:

{alert("Hello!");}

Here's more about that. Blocks sort of return values too, which is both awesome and disappointing.

Ry-
  • 218,210
  • 55
  • 464
  • 476
2

Because { a: 1, b: 2 } is not a valid expression to execute. JavaScript looks it like a block of code since it starts and ends to curly braces.

If you try ({ a: 1, b: 2 }), it will work.

ShankarSangoli
  • 69,612
  • 13
  • 93
  • 124
2

Because your statement is being evaluated as a block, not an object literal declaration.

True josh

If you want it to be evaluated as an object, just write :

> ({a : 1, b : 2})
Object
a: 1
b: 2
__proto__: Object
sinsedrix
  • 4,336
  • 4
  • 29
  • 53
1

Try this instead:

({ "a" : 1, "b" : 2 })
Anders Marzi Tornblad
  • 18,896
  • 9
  • 51
  • 66