You only need the parentheses (which are not "extra," since you need them!) when the parser is in a state where it's expecting a statement rather than an expression. So if you think in terms of: "Could I start an if
statement here?", if the answer is "Yes, I could" then you need the parens.
The reason is that when the parser is expecting a statement, if it sees the keyword function
, it assumes what follows is a function declaration, not a function expression.
To make the parser expect an expression, we don't have to use parens, any token that will make the parser expect an expression works. More information on that in this other answer.
So you don't need them after an =
, for instance (your example), because the parser is already expecting an expression on the right-hand side of the assignment. Similarly you don't need them after the :
in a property initializer:
var obj = {
foo: function() { /* ... */ }
};
...or when passing a function expression into a function as an argument:
foo(function() {
/* ... */
});
...that sort of thing.
But you need them here:
doSomething();
function() { /* ... */}(); // <== Fails
...because when it sees function
, the parser thinks it's going to be a function declaration, so:
doSomething();
(function() { /* ... */})(); // <== Works
Or
doSomething();
(function() { /* ... */}()); // <== Works
// Subtle diff here ----^^^
Or some more obscure examples:
doSomething();
+function() { /* ... */}(); // <== Works
doSomething();
!function() { /* ... */}(); // <== Works
doSomething();
~function() { /* ... */}(); // <== Works