Skip to content Skip to sidebar Skip to footer

What Do Braces Do In JavaScript?

I read this line in Eloquent JavaScript and would love some clarity. ...braces have two meanings in JavaScript. At the start of a statement, they start a block fo statements. In a

Solution 1:

as object literals

var a = {field1:value1, field2:value2}

as function bodies

function func() {
    // do something
}
var f = function() { /* do something */ };
var f = ()=>{}; // ditto

where the first item in the statement is an object literal

// {}.toString(); // syntax error, first brace of statement = code block
({}).toString(); // correct

as destructured assignment

var obj = {a:1, b:2, c:3};
var {a:x, c:y} = obj; // assign obj.a to x, and obj.c to y
({a:x, c:y} = obj); // ditto

Note - this has a lot of forms so I won't cover them all, full info found here (thanks RobG)

how this is interpreted

You can assume that all your JS code is inside some {} block. So the start of your code is immediately after a { always.

Wherever a value is expected, {} does not mean a function body. At the start of a statement this is ambiguous because you can have anonymous code blocks like so:

var x = 1;
{
    var x = x+2;
    // x = 3
}
// x = 3 (!)

This is archaic from C-style syntax where this would influence scope, but in testing this in JS it doesn't seem to have that effect, so for all intents it's rather useless syntax except to identify a code block. If you wanted such behavior you'd need to do this:

var x = 1;
(()=>{
    var x = x+2;
    // x = 3
})()
// x = 1

If we need an object first in some statement, we need to clarify to JS that we want a value. This is why we use ({}) instead of {}, because the former is unambiguously an object literal inside parens.


a simpler explanation

Rather than examine when {} is parsed as a value, let's look at when it isn't. There are two cases in general where we don't treat {} as an object literal: as a function body or as a statement group (my own term).

Consider the general control statements - if, for, while, with etc. These can all* be used in a way that completely avoids {}. In this respect {} should be thought of as statement groups hence the term.

if (x) x++; else x--;
if (x) {x++;} else {x--;}
{if (x) {x++;} else {x--;}}

*note: switch is an exception, switch(1); gives an error SyntaxError: missing { before switch body

Using this rule it then makes sense why we must use () to denote an object literal if it's the start of a statement - we can't start a statement in (), so you can't start a statement group there either, leaving only one option (object literal or related syntax).

This leaves function bodies.

function bodies

First, consider a function declaration statement:

function f () {}

It doesn't need a semicolon (;). This means the entire thing is a single statement. This explains why the following gives a syntax error in the first form but not the second:

function(){return 1;}(); // error: function statement requires name
var x = function(){return 1;}(); // fine

This is because the first is parsed as a statement, and a function declaration statement cannot be anonymous. However the second is in a value context and is treated as such. The situation is identical as with object literals, if it could be a statement it cannot be a value, but if we're already knee deep in value land, it has to be a value.

The => notation is, with one exception, parsed identically to function. The ()=>{} form is identical but in practice differs because this type of function cannot have a this object - it cannot be an object method (doesn't make much sense to) and it cannot construct new objects (it has no prototype), and other quirks as a result. otherwise it's straightforward to see how it's the same as function(){}.

()=>... however is a little different. It's treated as ()=>{return ...}. But, without the explicit } to finish the return statement, the syntax greedily captures the largest expression that would parse as such (not necessarily work). Case in point:

()=>1; // statement; = function that returns "1"
()=>1(); // statement; = function that returns "1()"
(()=>1()); // TypeError: 1 is not a function
(()=>1)(); // what was intended in above (you'd hope)

Post a Comment for "What Do Braces Do In JavaScript?"