I cannot remember where, but recently I passed a comment where the user told that 1TBS is more preferred than Allman in JavaScript and said Allman has dangerous implications in JavaScript.
Was it a valid statement? If so, why?
I cannot remember where, but recently I passed a comment where the user told that 1TBS is more preferred than Allman in JavaScript and said Allman has dangerous implications in JavaScript.
Was it a valid statement? If so, why?
return
cannot have LineTerminator
after it so:
return
{
};
is treated as return;
(return undefined
) instead of return {};
(return an object)
See the rules for Automatic Semicolon Insertion (ASI)
for more.
It is a valid statement.
Because JavaScript's engines have what's called ASI (Automatic Semicolon Insertion) which inserts a semicolon if necessary at lines returns. The "if necessary" is ambiguous; sometimes it works and sometimes doesn't. See the rules.
So, as said in the other answers:
return
{
};
// Is read by the JavaScript engine, after ASI, as:
return; // returns undefined
{ // so this is not even executed
};
So it's not recommended for return
statements.
However, if your guidelines recommend the Allman style for function declarations, it's perfectly fine. I know some that do.
I think it depends on the statement. For example a return statement might be broken if opening brace is on new line. More info here.
return {
a: "A",
b: "B"
};
// vs.
return // Semicolon automatically inserted here! Uh oh!
{
a: "A",
b: "B"
}
You can use Allman or Allman-8 style just fine as long as you remember one special case with keywords return
and throw
.
Separating object literals from keywords return
or throw
by a linefeed doesn't work in JavaScript because of ASI rules which have a special exception for throw
and return
statements:
- When, as the program is parsed from left to right, a token is encountered that is allowed by some production of the grammar, but the production is a restricted production and the token would be the first token for a terminal or nonterminal immediately following the annotation “[no LineTerminator here]” within the restricted production (and therefore such a token is called a restricted token), and the restricted token is separated from the previous token by at least one LineTerminator, then a semicolon is automatically inserted before the restricted token.
and
NOTE The following are the only restricted productions in the grammar:
[...]
ReturnStatement :
return
[no LineTerminator here] Expression ;
ThrowStatement :
throw
[no LineTerminator here] Expression ;
(There are other restricted productions, too, but those don't support braces so they are not important for Allman style.)
In practice, this doesn't work as you would expect:
return
{
status: "successful",
user:
{
id: "9abf38a3-c2f5-4159-a1be-0eccbc1b2349",
label: "John Doe",
},
};
because it will be interpreted as (note the semicolon after return!)
return;
{
status: "successful",
user:
{
id: "9abf38a3-c2f5-4159-a1be-0eccbc1b2349",
label: "John Doe",
},
};
So, you have to either use syntax
const response =
{
status: "successful",
user:
{
id: "9abf38a3-c2f5-4159-a1be-0eccbc1b2349",
label: "John Doe",
},
};
return response;
or
return {
status: "successful",
user:
{
id: "9abf38a3-c2f5-4159-a1be-0eccbc1b2349",
label: "John Doe",
},
};
instead.
I personally think that naming the returned structures is more readable in any case, so I use that. I also use Allman-8 everywhere which practically means that you use 8 space width tab characters and indent everything with a single tab character instead of 1 or more spaces.
In theory, somebody could also write
throw
{
status: "error",
code: 12,
details: localvar,
};
which would also fail because a semicolon would be inserted immediately after the keyword throw
because of the ASI rules above. In real world, everybody seems to write throw new ...
or throw localvar
.
I don't know the history for these exceptions but I can only assume it's some historical mishap that cannot be fixed anymore because of existing real world code depending on this mishap. I fail to see any construct where this automatic semicolon would actually be beneficial so I think this is just a bug in historical specification. (The code following return
or throw
cannot reasonably start with an object literal so it wouldn't work anyway with the inserted semicolon.)