Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between those self-executing anonymous function (aka IIFE) implementation

Tags:

javascript

In many books / blog posts the self invoking anonymous function pattern is written like this:

(function() {
  var foo = 'bar';
})();

However running a JSLint on this gives this error:

Move the invocation into the parens that contain the function.

e.g. changing it to this works:

(function() {
  var foo = 'bar';
}());

Questions

  1. Why is the first implementation not good enough for JSLint? What are the differences?
  2. What is the preferred form? is JSLint always right?
  3. Why does it work? after all function(){}() throws a SyntaxError: Unexpected token (
    But wrapping it with parens makes it all of a sudden work? e.g. (function(){}()) - works fine
    (After all this is JavaScript, not Lisp, so what is the effect of the wrapping parens on the ohterwise syntax error?)

EDIT: this is somewhat of a followup to this (I would not say exact duplicate though): JSLint error: "Move the invocation into the parens that contain the function", so my main question is #3, why does it work at all?

like image 351
Eran Medan Avatar asked Apr 16 '13 00:04

Eran Medan


2 Answers

I don't know how Crockford's opinions were developed, but I can explain why wrapping in parens works.

The function function() { ... } syntax in JavaScript can represent two different things: a function declaration or a function expression.

A function declaration is a statement that defines the function within the current scope under the specified name.

function example() { 
    alert("Hello World");
}

example();

A function expression is an expression that evaluates to a new Function instance.

var secondExample = function example() {
    alert("Hello World");
};

secondExample();
example(); // <-- throws an Error: example is not defined.

Whether a occurrence of the syntax is a function declaration or function statement depends on what the parser was expecting. JavaScript's parser is simple. It won't look ahead and notice that the function is followed by (), therefore it should treat it as a expression. It just sees the function at the beginning of a line, and therefore treats it as a statement, which causes a syntax error when it's followed by (). When you wrap it in parentheses, the parser is instead expecting an expression, and it works.

Wrapping in parentheses (wherever you place them) is the the clearest way to do this, but anything that causes the parser to expect an expression will work. For example, the bitwise NOT operator ~:

~function() {
    alert("Hello World");
}();
like image 52
Jeremy Avatar answered Oct 23 '22 05:10

Jeremy


1.

Apparently this is an issue with conventions. Having the first example shows a "lack of convention" (source). As far as actual differences, there are none. Both will execute without error.

2.

In this case, I prefer your first example, but that is just my convention. JSLint is often right. So if you want to follow their naming conventions then when it shows a warning based on convention it would make sense to conform to the convention.

3.

This works because wrapping the function(){} inside of a () makes it an expression, which once paired with the final () immediately invokes it. Hence you have an Immediately Invoked Function Expression.

like image 25
Travis J Avatar answered Oct 23 '22 06:10

Travis J