开发者

Why would one write global code inside a function definition-call pair?

开发者 https://www.devze.com 2023-01-01 01:30 出处:网络
I see examples where JavaScript code including jQuery and jslint use the notation below: (function(){ // do something

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?


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


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.


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.


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.


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 :)

0

精彩评论

暂无评论...
验证码 换一张
取 消