3

I have these functions:

function A1()
{
    return B() && C();
}

function A2()
{
    return
        B() && 
        C();
}

function B()
{
    return true;
}

function C()
{
    return true;
}

Calling A1 returns true, but A2 returns undefined. The only difference between A1 and A2 is white space. What is going on? In my real code, I do not want to write my A1 function a as a single line because it will be very long and not very readable.

Polyfun
  • 9,089
  • 4
  • 29
  • 39
  • 1
    Check here http://stackoverflow.com/questions/12745743/automatic-semicolon-insertion-return-statements – elclanrs Jul 02 '13 at 09:46
  • 1
    Javascript ASI. Oh joy. http://stackoverflow.com/questions/2846283/what-are-the-rules-for-javascripts-automatic-semicolon-insertion-asi – Jon Jul 02 '13 at 09:47

2 Answers2

7

You are falling victim to automatic semicolon insertion. The interpreter will add a semicolon after your return statement, so this is effectively what's happening:

function A2()
{
    return;
    //    ^ Automatically inserted semicolon
        B() && 
        C();
}

Since you now have a return statement with no explicit return value, the function will return undefined.

If you look at the grammar for return statements in the spec:

ReturnStatement :
  return [no LineTerminator here] Expression;

You can see that it does not allow line terminators between the return keyword and the expression (this is known as a "restricted production"). If a line terminator is encountered, the third rule of automatic semicolon insertion applies:

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.


I do not want to write my A1 function a as a single line because it will be very long...

You can still break your return statement over multiple lines, you just need to be careful about where you put the line breaks (just make sure they occur in the Expression rather than before it):

function A2()
{
    return B() &&
    //           ^ Invalid to put a semicolon here, so ASI doesn't apply
        C();
}
James Allardice
  • 156,021
  • 21
  • 318
  • 304
1
return (
    B() && 
    C()
);

will work as well

David Fregoli
  • 3,282
  • 1
  • 16
  • 37