Why JS throws syntax error, if there is a linefeed between return and {

1.5k views Asked by At

I always thought, that new lines in JS sourcecode doesn't matter. Why new lines do matter sometimes?

Error:

function x(y)
{
    return 
    {   y : y,
        z : y*2
    } 
}
console.info(x(5).z);

Throws a SyntaxError: missing ; before statement at z : y*2 (pointing to the :)

But this is working:

function x(y)
{
    return (
    {   y : y,
        z : y*2
    } )
}
console.info(x(5).z);

shows 10

This is also working:

function x(y)
{
    return {
        y : y,
        z : y*2
    } 
}
console.info(x(5).z);
3

There are 3 answers

1
pdem On BEST ANSWER

There are 2 problems: The ";" are automaticaly added by the browser on the return line, and you missed one ";" after the object declaration in the return. You should never rely on automatic addition of ";", because you wouldn't be abble to minify your javascript code after that.

You wouldn't have this problem by using the "1TBS" notation. (a notation that i also call the "Egyptian Notation"): So always put the curly brace at the end of the previous statement. http://en.wikipedia.org/wiki/Indent_style

The question has already be debatted here: Is there a way I can make jslint work with curly braces on the next line of my javascript?

So the right notation for your code should be:

function x(y){
    return {
        y : y,
        z : y*2
    }; 
}
console.info(x(5).z);

You may use jshint to check your code style.

0
T.J. Crowder On

Newlines matter in JavaScript because of Automatic Semicolon Insertion, which is the idea that the parser will insert "missing" semicolons according to the rules laid out in the spec.

In your code, it will insert a ; after the return, before the lines that follow.

With the automatically-inserted ; present, it's clear why there's a syntax error:

function x(y)
{
    return ; // <== Added by ASI
    {   y : y,
        z : y*2
    } 
}
console.info(x(5).z);

Now, the { after the ; is the beginning of a block, not an object initializer, and so the parser sees the y as a statement label, and then it sees what looks like the beginning of an expression statement for the comma operator, but the : after the z is invalid at that location, so there's an error.

ASI doesn't apply within an expression, though, which is why both

return {
    y: y,
    z: y*2
};

and

return (
{
    y: y,
    z: y*2
});

work.

0
Jon On

Because of automatic semicolon insertion (AST), which the return statement is subject to. Since the line the statement appears in does not end with a semicolon the compiler automatically adds one. Therefore you are left with this:

return;
{   y : y,
    z : y*2
}

which is a return statement followed by an obviously unreachable code block. The code within the block is syntactically invalid and you get the aforementioned error.

Adding an opening paren or the object literal's opening brace on the same line as return prevents AST from working because adding a semicolon after it would cause the return statement itself to be syntactically invalid.