9

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?

Community
  • 1
  • 1
Eran Medan
  • 44,555
  • 61
  • 184
  • 276
  • 2
    Many, many duplicates. In short, 1-2: Because Crockford prefers so. JSHint was created just because JSLint is too biased. 3. Because the identifier is optional for function expressions while it is mandatory for a function declaration (the parens make it a function expression). See http://kangax.github.io/nfe/#expr-vs-decl – Fabrício Matté Apr 16 '13 at 00:43
  • I don't use JSLint. If you do, understand it is a biased tool. I *prefer* to consistently use the form `;(function ..)()` - the leading `;` prevents a potentially more obscure error. Both forms lead to equivalent syntax trees. – user2246674 Apr 16 '13 at 00:46
  • 3
    @user2246674 Did you mistype a H for an L? `:P` – Fabrício Matté Apr 16 '13 at 00:48
  • 1
    Possible duplicates: http://stackoverflow.com/q/3783007/1331430 http://stackoverflow.com/q/3384504/1331430 http://stackoverflow.com/q/423228/1331430 http://stackoverflow.com/questions/5938802/are-function-and-function-functionally-equal-i (and still I didn't find the one I was looking for...) – Fabrício Matté Apr 16 '13 at 00:49
  • @FabrícioMatté: Eh. They're both rather opinionated; the whole purpose of both is to automate validation against someone's idea of proper coding conventions. One (JSHint) just happens to be a bit less so than the other (JSLint). – cHao Apr 16 '13 at 00:50
  • 1
    @FabrícioMatté Yes, yes I did. – user2246674 Apr 16 '13 at 00:50
  • @cHao True that, least most of the "opinionated" stuff can be easily turned off in JSHint, while in JSLint I didn't even find the option to turn the indentation/white space check off yet. – Fabrício Matté Apr 16 '13 at 00:54
  • @FabrícioMatté: Yeah, JSLint is biased as hell. Frankly, Crockford's quite the arrogant SOB sometimes, thinking his way is the One True Way to Write JavaScript(tm). No wonder JSHint happened. :) – cHao Apr 16 '13 at 00:57
  • @cHao lol yes, I've learned a lot reading his articles and watching presentations, though fulfilling JSLint's "code quality standard" is more of a self-challenge pass-time than a productive thing. `:P` – Fabrício Matté Apr 16 '13 at 00:59
  • @FabrícioMatté - in sublime text 2 the JS Formatter has a JSLint friendly option (default off though), this plus the trailing spaces plugin makes being JSLint compliant almost fun bearable :) – Eran Medan Apr 16 '13 at 01:02
  • @EranMedan good to know. `:P` Right now I only use ST for CSS and LESS, but once ST gets GIT integration as NetBeans' I'll probably switch JS and PHP over too. `:P` – Fabrício Matté Apr 16 '13 at 01:04
  • @FabrícioMatté yep, if you are not a VIM person, ST or WebStorm seem to be the best JS editors / IDEs out there (till brackets matures) the latter has a 50% off this week :) but I'm way off topic for an SO comment! – Eran Medan Apr 16 '13 at 01:08

2 Answers2

6

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");
}();
Jeremy
  • 1
  • 85
  • 340
  • 366
  • Neither pattern shown is a FunctionDeclaration and while this does address #3, it really goes on a tangent .. – user2246674 Apr 16 '13 at 00:48
  • 1
    I don't understand how the first one is not a FunctionDeclaration. Per [the spec](http://www.ecma-international.org/ecma-262/5.1/#sec-13), a FunctionDeclration is `function Identifier ( FormalParameterListopt ) { FunctionBody }`, and my example matches. – Jeremy Apr 16 '13 at 00:50
  • 1
    `(function() {})()` (first form) vs. `(function() {}())` (second form) vs `function(){}()` (in question #3). Of course question #3 fail to address context as `x = function(){}()` would once again be valid (and not a FunctionDeclaration). – user2246674 Apr 16 '13 at 00:51
  • 1
    Oh, you mean the example in the question. That's true, but this distinction is necessary to explain (3). – Jeremy Apr 16 '13 at 00:51
  • Note that there are other ways of forcing the function to be interpreted as an expression, e.g. _!function(){}();_ – nnnnnn Apr 16 '13 at 00:55
  • Great explanation, thanks! it might be a duplicate question, but the others didn't have answers that explain it that well (or perhaps I skimmed it too fast) indeed interesting explanation from the parser side – Eran Medan Apr 16 '13 at 00:58
1

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.

Travis J
  • 81,153
  • 41
  • 202
  • 273