12

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?

Braiam
  • 1
  • 11
  • 47
  • 78
Ajax3.14
  • 1,647
  • 5
  • 24
  • 42
  • 1
    There are more statements affected by ASI, check the spec. link that @Esailija posted or give a look to [this answer](http://stackoverflow.com/questions/2846283/what-are-the-rules-for-javascripts-automatic-semicolon-insertion/2846298#2846298), I summarized the ASI rules there... Ah, and just for fun, *try* to pass the following test: [ASI Test](http://asi.qfox.nl/) – Christian C. Salvadó Jun 28 '12 at 15:17
  • See also [Is block style really this important?](http://stackoverflow.com/q/3004496/1048572) – Bergi Sep 17 '16 at 21:21

5 Answers5

21

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.

Esailija
  • 138,174
  • 23
  • 272
  • 326
  • Maybe saying that it's related to ASI is a plus to the answer? – Florian Margaine Jun 28 '12 at 14:56
  • 5
    I have grown to really like javascript, but this is still really weird – NimChimpsky Jun 28 '12 at 14:56
  • @FlorianMargaine Give me a moment – Esailija Jun 28 '12 at 14:57
  • 2
    [A good quick rant on using semicolons.](http://benalman.com/news/2012/04/semicolons-required-in-javascript/) To paraphrase: `Semicolons are required in JavaScript; they’re just not required in YOUR JavaScript.` – lbstr Jun 28 '12 at 15:02
  • Allman style is a *lot* more than just `return` statement. If you return with a named variable there will be no problems. You can use full Allman style everywhere else and I'd claim that using syntax `return response` is more readable than `return { foo:bar, zoo: 1}` anyway. – Mikko Rantalainen Feb 02 '22 at 09:33
  • ASI rules are really weird. If you *believe* that semicolons are optional and don't want to write those, try this test: http://asi.qfox.nl/ – you can keep leaving the semicolons off if you and your whole teams gets full points. Otherwise, stop using that misfeature and write the missing semicolons by yourself. – Mikko Rantalainen Feb 02 '22 at 09:40
3

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Florian Margaine
  • 58,730
  • 15
  • 91
  • 116
2

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.

septemberbrain
  • 998
  • 9
  • 25
  • The link seems to be broken. Also, Stackover style recommends not using link only answers and you should explain the answer here, instead. – Mikko Rantalainen Feb 02 '22 at 09:37
2
return {
    a: "A",
    b: "B"
};

// vs.

return // Semicolon automatically inserted here! Uh oh!
{
    a: "A",
    b: "B"
}
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
lbstr
  • 2,822
  • 18
  • 29
0

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:

  1. 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.)

Mikko Rantalainen
  • 14,132
  • 10
  • 74
  • 112