6

I see examples where JavaScript code including jQuery and jslint use the notation below:

(function(){
  // do something
})();

instead of:

// do something

I first thought this is just for local scoping, i.e. creating local variables for the code block without polluting global namespace. But I've seen instances without any local variables at all too.

What am I missing here?

Sedat Kapanoglu
  • 46,641
  • 25
  • 114
  • 148

5 Answers5

8

It's about scope for functions, too - everything declared within the code block is scoped to that anonymous function only. Things are normally made public by the framework

(function($) {

  var localVarOnly = "local";

  $.fn.myCoolFunction = function() { // in the case of jquery, make this publicly available
    otherCoolFunction(); //alerts hi
    alert(localVarOnly); // alerts local
  };

  function otherCoolFunction() { // scoped to this anonymous function only
    alert('hi');
  };

})(jQuery);

otherCoolFunction(); // undefined
alert(localVarOnly); // undefined
Dan Heberden
  • 10,990
  • 3
  • 33
  • 29
4

As everyone else has said, it's pretty much entirely to do with creating local scope. Another benefit is that you can use it to (for want of a better word) "rename" variables. Take for instance, how several javascript frameworks use $ as a shorthand for their main library function. If you create a closure like in your example, it doesn't matter what $ is outside, you can use it as a parameter and inside it can be whatever you want:

// out here $ might be Prototype, something else, or even undefined
(function($) {
    // in here, $ is jQuery
})(jQuery);

Another little tip for eking an extra couple of milliseconds of your script is to use this same technique to create an undefined variable. Most people think that undefined is a special keyword in javascript, but it's actually just treated as a normal variable, which you'd hope no one would define. The somewhat standard practice of checking for a undefined variable:

if (x == undefined)

...is actually rather wasteful, since it checks the entire scope chain for a variable named "undefined". To shortcut this, you can use this method:

(function($, undefined) {
    // code here
})(jQuery);  // note that there's just one parameter passed

Now that undefined is actually in a scope (with an undefined value), checking up the scope chain can stop at that point. Micro-optimisation, yes, but it doesn't hurt to know.

nickf
  • 537,072
  • 198
  • 649
  • 721
  • Regarding optimization of `undefined` variable: isn't it still faster to test for string `"undefined"` instead of comparing against a variable (with ‘coincidentally’ the same name)? – Marcel Korpel Jun 09 '10 at 22:41
  • @Marcel - I just did a test (1,000,000 iterations of both methods). Using `typeof x == "undefined"` took ~2050ms. Using `x == undefined` took ~34ms. – nickf Jun 09 '10 at 23:20
  • How did you test this? E.g., if I use [this test case](http://pastie.org/999172) in Firefox, there's hardly any difference between the two, but in Chromium `typeof x == "undefined"` is significantly faster than `typeof x == undefined`. Testing for `x == undefined` only works when `x` is defined (otherwise an error is thrown); timings hardly differ in Firefox and it is even slightly slower in Chromium than testing `typeof x == "undefined"` when `x` is defined. – Marcel Korpel Jun 10 '10 at 11:53
  • @Marcel, in that test you pasted you didn't "define" `undefined` like in my last code sample above. Changing the test so that there is a closure with a variable named `undefined` left undefined meant the code ran 55% faster on my PC (Firefox 3.6.3) – nickf Jun 10 '10 at 13:39
  • Yes, of course, that was what your second tip was all about. But it still only works when `x` is defined or explicitly set to `undefined` as an argument to the anonymous function (like the variable `undefined` in your example). A really undefined variable, like in the case I pasted, throws an error when testing `x == undefined` (“Uncaught ReferenceError: x is not defined” in Chrome and “x is not defined” in Firefox). BTW, ~34ms is not 55% faster than ~2050ms. A typo somewhere? – Marcel Korpel Jun 10 '10 at 13:52
3

The main purpose of this (Crockford's) pattern (there are others -- in some cases more performant -- too) is to avoid the pollution of the global scope with named functions/identifiers. By doing stuff within this anonymous closure, you can write your code as you'd do inside the global scope, except that everything declared inside remains local and thus cannot be accessed/referenced from outside. Use-cases where no local variables/functions are used or "exported" (assigned to a named identifier from one of the outer scopes), might exist, but don't necessarily have to be nested within a anonymous funciton.

petabyte
  • 397
  • 2
  • 11
3

That syntax is to create local scope, as others have commented, but also to make the function self-executing. Note that simply creating local scope could also be accomplished like this:

var foo = function(){
   // local code
};
foo();

But if that's all you're doing, and foo has no other utility beyond calling it one time, then the anonymous, self-executing syntax simply saves you the extra var declaration:

(function(){
   // local code
})();

In frameworks that use OOP patterns, this is also the syntax used to create singletons since the function can only run once and can never be called again by external code.

Brian Moeskau
  • 20,103
  • 8
  • 71
  • 73
1

This is to create a scope that will contain all the variables declared. This is to avoid polluting the global scope and to avoid overriding already existing variables.

Take this example

(function() {
    var foo = "bar";
    var undefined = true;
    var bar = true;

    alert(foo); //bar
    if (bar == undefined) {
        alert("bar is undefined.. not!"); //will show even though we know that bar is not 'undefined'
    }

})();

var bar = true;
alert(foo) //undefined
if (bar == undefined) {
    alert("bar is undefined"); // will not be called
}

When it comes to the pattern, (function(){/*....*/})(); there is currently a debate going on at comp.lang.javascript about what to call this construct, and who should get the credit for it :)

Sean Kinsey
  • 37,689
  • 7
  • 52
  • 71
  • 2
    That's one reason and I'd already figured that out (see my question :). – Sedat Kapanoglu May 24 '10 at 15:26
  • 1
    Are you saying that there is no purpose in putting a code block in a function if you don't use any local variables? Because if you see my question I've seen examples where this notation is used without any variables at all. – Sedat Kapanoglu May 24 '10 at 15:37
  • 1
    It's one of the main purposes, but not the only one. Anonymous closures are f.e. used for obfuscating/protecting specific code parts against modification from outside or to "break" closures so that composite objects (Object, Array, Functions) get really duplicated. – petabyte May 24 '10 at 15:47
  • Thats pretty much the same thing - scoping by definition ;) – Sean Kinsey May 24 '10 at 15:55
  • @ssg that is correct, if you dont define **anyting** (no variables, no functions) then there is absolutely no point in doing it. – Sean Kinsey May 24 '10 at 15:56
  • No it's not the same thing. When you want to really duplicate a object, in 99,9% of all cases one is going to call multiple nested anonymous functions to accomplish that. Alone this is a adequate use-case. – petabyte May 24 '10 at 16:00
  • @peta scoping has nothing to do with duplicating an object - you should probably read up on the spec. This I know. If you are referring to passing arguments to the invoked function then this is only creating new `references` to the same objects, references that can be replaced without disturbing the variable holding the first reference. – Sean Kinsey May 24 '10 at 16:04
  • @peta and about your use-case; what? – Sean Kinsey May 24 '10 at 16:11
  • @Sean Kinsey: Sorry, you're right. I totally confused it with reference storing of composite objects what only can be "broken" by using two anonymous closures. :) – petabyte May 27 '10 at 22:37