开发者

Why is this function wrapped in parentheses, followed by parentheses? [duplicate]

开发者 https://www.devze.com 2023-03-01 01:34 出处:网络
This question already has answers here: What is the (function() { } )() construct in JavaScript? (28 answers)
This question already has answers here: What is the (function() { } )() construct in JavaScript? (28 answers) Closed 9 years ago.

I see this all the time in javascript sources but i've never really found out the real reason this construct is used. Why is this needed?

(function() {

开发者_如何转开发    //stuff

})();

Why is this written like this? Why not just use stuff by itself and not in a function?

EDIT: i know this is defining an anonymous function and then calling it, but why?


This defines a function closure

This is used to create a function closure with private functionality and variables that aren't globally visible.

Consider the following code:

(function(){
    var test = true;
})();

variable test is not visible anywhere else but within the function closure where it's defined.

What is a closure anyway?

Function closures make it possible for various scripts not to interfere with each other even though they define similarly named variables or private functions. Those privates are visible and accessible only within closure itself and not outside of it.

Check this code and read comments along with it:

// public part
var publicVar = 111;
var publicFunc = function(value) { alert(value); };
var publicObject = {
    // no functions whatsoever
};

    // closure part
    (function(pubObj){
        // private variables and functions
        var closureVar = 222;
        var closureFunc = function(value){
            // call public func
            publicFunc(value);
            // alert private variable
            alert(closureVar);
        };

        // add function to public object that accesses private functionality
        pubObj.alertValues = closureFunc;

        // mind the missing "var" which makes it a public variable
        anotherPublic = 333;

    })(publicObject);

// alert 111 & alert 222
publicObject.alertValues(publicVar);

// try to access varaibles
alert(publicVar); // alert 111
alert(anotherPublic); // alert 333
alert(typeof(closureVar)); // alert "undefined"

Here's a JSFiddle running code that displays data as indicated by comments in the upper code.

What it actually does?

As you already know this

  1. creates a function:

    function() { ... }
    
  2. and immediately executes it:

    (func)();
    
  3. this function may or may not accept additional parameters.

jQuery plugins are usually defined this way, by defining a function with one parameter that plugin manipulates within:

(function(paramName){ ... })(jQuery);

But the main idea is still the same: define a function closure with private definitions that can't directly be used outside of it.


That construct is known as a self-executing anonymous function, which is actually not a very good name for it, here is what happens (and why the name is not a good one). This:

function abc() {
    //stuff
}

Defines a function called abc, if we wanted an anonymous function (which is a very common pattern in javascript), it would be something along the lines of:

function() {
    //stuff
}

But, if you have this you either need to associate it with a variable so you can call it (which would make it not-so-anonymous) or you need to execute it straight away. We can try to execute it straight away by doing this:

function() {
    //stuff
}();

But this won't work as it will give you a syntax error. The reason you get a syntax error is as follows. When you create a function with a name (such as abc above), that name becomes a reference to a function expression, you can then execute the expression by putting () after the name e.g.: abc(). The act of declaring a function does not create an expression, the function declaration is infact a statement rather than an expression. Essentially, expression are executable and statements are not (as you may have guessed). So in order to execute an anonymous function you need to tell the parser that it is an expression rather than a statement. One way of doing this (not the only way, but it has become convention), is to wrap your anonymous function in a set of () and so you get your construct:

(function() {
    //stuff
})();

An anonymous function which is immediately executed (you can see how the name of the construct is a little off since it's not really an anonymous function that executes itself but is rather an anonymous function that is executed straight away).

Ok, so why is all this useful, one reason is the fact that it lets you stop your code from polluting the global namespace. Because functions in javascript have their own scope any variable inside a function is not visible globally, so if we could somehow write all our code inside a function the global scope would be safe, well our self-executing anonymous function allows us to do just that. Let me borrow an example from John Resig's old book:

// Create a new anonymous function, to use as a wrapper
(function(){
  // The variable that would, normally, be global
  var msg = "Thanks for visiting!";
  // Binding a new function to a global object
  window.onunload = function(){
    // Which uses the 'hidden' variable
    alert( msg );
  };
  // Close off the anonymous function and execute it
})();

All our variables and functions are written within our self-executing anonymous function, our code is executed in the first place because it is inside a self-executing anonymous function. And due to the fact that javascript allows closures, i.e. essentially allows functions to access variables that are defined in an outer function, we can pretty much write whatever code we like inside the self-executing anonymous function and everything will still work as expected.

But wait there is still more :). This construct allows us to solve a problem that sometimes occurs when using closures in javascript. I will once again let John Resig explain, I quote:

Remember that closures allow you to reference variables that exist within the parent function. However, it does not provide the value of the variable at the time it is created; it provides the last value of the variable within the parent function. The most common issue under which you’ll see this occur is during a for loop. There is one variable being used as the iterator (e.g., i). Inside of the for loop, new functions are being created that utilize the closure to reference the iterator again. The problem is that by the time the new closured functions are called, they will reference the last value of the iterator (i.e., the last position in an array), not the value that you would expect. Listing 2-16 shows an example of using anonymous functions to induce scope, to create an instance where expected closure is possible.

// An element with an ID of main
var obj = document.getElementById("main");

// An array of items to bind to
var items = [ "click", "keypress" ];

// Iterate through each of the items
for ( var i = 0; i < items.length; i++ ) {
  // Use a self-executed anonymous function to induce scope
  (function(){
    // Remember the value within this scope
    var item = items[i];
    // Bind a function to the element
    obj[ "on" + item ] = function() {
      // item refers to a parent variable that has been successfully
      // scoped within the context of this for loop
      alert( "Thanks for your " + item );
    };
  })();
}

Essentially what all of that means is this, people often write naive javascript code like this (this is the naive version of the loop from above):

for ( var i = 0; i < items.length; i++ ) {
    var item = items[i];
    // Bind a function to the elment
    obj[ "on" + item ] = function() {
      alert( "Thanks for your " + items[i] );
    };
}

The functions we create within the loop are closures, but unfortunately they will lock in the last value of i from the enclosing scope (in this case it will probably be 2 which is gonna cause trouble). What we likely want is for each function we create within the loop to lock in the value of i at the time we create it. This is where our self-executing anonymous function comes in, here is a similar but perhaps easier to understand way of rewriting that loop:

for ( var i = 0; i < items.length; i++ ) {
  (function(index){
    obj[ "on" + item ] = function() {
      alert( "Thanks for your " + items[index] );
    };
  })(i);
}

Because we invoke our anonymous function on every iteration, the parameter we pass in is locked in to the value it was at the time it was passed in, so all the functions we create within the loop will work as expected.

There you go, two good reasons to use the self-executing anonymous function construct and why it actually works in the first place.


It's used to define an anonymous function and then call it. I haven't tried but my best guess for why there are parens around the block is because JavaScript needs them to understand the function call.

It's useful if you want to define a one-off function in place and then immediately call it. The difference between using the anonymous function and just writing the code out is scope. All the variables in the anonymous function will go out of scope when the function's over with (unless the vars are told otherwise, of course). This can be used to keep the global or enclosing namespace clean, to use less memory long-term, or to get some "privacy".


It is an "anonymous self executing function" or "immediately-invoked-function-expression". Nice explanation from Ben Alman here.

I use the pattern when creating namespaces

var APP = {};

(function(context){



})(APP);


Such a construct is useful when you want to make a closure - a construct helps create a private "room" for variables inaccessible from outside. See more in this chapter of "JavaScript: the good parts" book: http://books.google.com/books?id=PXa2bby0oQ0C&pg=PA37&lpg=PA37&dq=crockford+closure+called+immediately&source=bl&ots=HIlku8x4jL&sig=-T-T0jTmf7_p_6twzaCq5_5aj3A&hl=lv&ei=lSa5TaXeDMyRswa874nrAw&sa=X&oi=book_result&ct=result&resnum=1&ved=0CBUQ6AEwAA#v=onepage&q&f=false

In the example shown on top of page 38, you see that the variable "status" is hidden within a closure and cannot be accessed anyway else than calling the get_status() method.


I'm not sure if this question is answered already, so apologies if I'm just repeating stuff.

In JavaScript, only functions introduce new scope. By wrapping your code in an immediate function, all variables you define exist only in this or lower scope, but not in global scope.

So this is a good way to not pollute the global scope.

There should be only a few global variables. Remember that every global is a property of the window object, which already has a lot of properties by default. Introducing a new scope also avoids collisions with default properties of the window object.

0

精彩评论

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