cst1992
cst1992

Reputation: 3941

Function is working when assigned to a variable but throwing SyntaxError when executed by itself

I had an IIFE like this one:

(function a() {
    return "b";
}());

Executed in the console, it returns "b".

I removed the first set of parentheses, thinking that this'll make the "a" function global, but still work, and return "b":

function a() {
   return "b";
}();

But it throws a SyntaxError:

Uncaught SyntaxError: Unexpected token )

Then, I tried converting the function to an expression by assigning to a variable, and it worked:

var c = function a() {
   return "b";
}();
console.log(c); // prints b

Why does this happen? Why is it working as an expression but not by itself?

Upvotes: 1

Views: 35

Answers (1)

cst1992
cst1992

Reputation: 3941

The second piece of code is not what it looks like.

This code looks like a function that is being immediately executed:

function a() {
    return "b";
}()

But in reality, it's just a function declaration followed by an empty expression, which is not allowed:

function a() {
    return "b";
}

() // not allowed - empty expression

Ben Alman explains this in his article on IIFE's:

When the parser encounters the function keyword in the global scope or inside a function, it treats it as a function declaration (statement), and not as a function expression, by default.

...

While parens placed after an expression indicate that the expression is a function to be invoked, parens placed after a statement are totally separate from the preceding statment, and are simply a grouping operator (used as a means to control precedence of evaluation).

The grouping operator needs to contain an expression to evaluate. By itself it's of no meaning:

() // meaningless
2 + 3 * 4 // 15
(2 + 3) * 4 // 20

In IIFE's, the outer parentheses are just a means of forcing the parser to expect an expression.

This is why the expression var c = function() { return "b"; }(); also works; it's because the parser knows to expect an expression because of the assignment to c.

Side Note

Alman also recommends against using self-invoking functions without using the outer parentheses when assigning to variables(i.e. var v = function(){...}()) because it's bad practice:

In cases where the extra “disambiguation” parens surrounding the function expression are unnecessary (because the parser already expects an expression), it’s still a good idea to use them when making an assignment, as a matter of convention.

Such parens typically indicate that the function expression will be immediately invoked, and the variable will contain the result of the function, not the function itself. This can save someone reading your code the trouble of having to scroll down to the bottom of what might be a very long function expression to see if it has been invoked or not.

Upvotes: 4

Related Questions