English 中文(简体)
Scope with a self-invoking function in Javascript
原标题:

Take below code iterates over 6 input buttons and attaches an onclick event to every button that alerts the index number of the respective iteration:

for (var i = 1; i < 6; ++i) {
    var but = document.getElementById( b_  + i);
    (function (el) {
        var num = i;
        but.onclick = function () {
            alert(num);
        };
    })(but);
}

As you can see, in each iteration there is a self-invoking function that creates a scope to store the iteration index in that scope.

I have always used this type of pattern to attach an event that is dependant on a variable that is changed during iterations.


Can anyone explain to me exactly why the above works, and how the num variable is captured in the scope?

Also, is the self-invoking function used above called a closure ?

最佳回答

Yes this is a closure.

Everytime a function is executed a new object is created to hold (as its properties) the variables that are declared with var and every function declared inside it. This object is called the execution context (or sometimes the scope object).

Everytime a function is declared (or defined in an expression) the new function has attached to it the execution context object that is current. This creates what is known as a scope chain.

When executing code needs to resolve an identifier to a value it first looks for it in the properties of the current execution context. If the identifier is not found it uses the exection context object attached to the function that is being executed. It keeps going up the scope chain until it reaches the global level.

In your example each time "self-invoking function" gets executed a new execution context object is create holding the properies el and num. Since the function assigned to onclick is created inside this execution context you will get a new instance of this function each time. These instances will each have the corresponding execution context object attached. Hence the first will have the execution context when num has been assigned 1, the second will have the execution context where num has been assigned 2 and so on.

When each of the onclick functions run the code will initially look for the identifier num in the current execution context. However this inner function doesn t var a num so its not found. So Javascript looks to the execution context attached to the function when it was created. Here it will find num, the num will contain the value assigned to it during that iteration as described above.

问题回答

Hey guys. Yep it is a closure. If you want to know what exactly occurs when function is creating then study following article. http://www.jibbering.com/faq/faq_notes/closures.html

Wouldn t that mean that the var i defined outside the closure is a global variable, thus giving the self-invoking function access to it?

Each time through the loop, evaluating function (el) {...} creates a new anonymous function, which is immediately invoked. Within the anonymous function, a variable named num is created (because JS doesn t do static variables, it s a new one each time). num is assigned the value of i when the function is invoked (which is immediately). This gives us 6 anonymous functions and 6 nums, each holding the values 1 through 6.

With each invocation of the anonymous function, an inner anonymous function is created and stored as the click handler. The inner function references a num. As a result, a closure is created which ensure that when the outer function exits, num isn t destroyed. Should the inner function ever be discarded, num will soon follow.

for (var i = 1; i < 6; ++i) {
    var but = document.getElementById( b_  + i);
    (function (el) {
        var num = i;
        but.onclick = function () {
            alert(num);
        };
    })(but);
}

Now lets start the execution of the loop
initially i=1,but= domelement with id = b1
now comes the function invoke,
ok it calls the inner function(with parameter el) with value of parameter of but( b1 ) and starts executing it that is what invoking actually means execute it now.
Now inside it ,
new instance of num is assigned 1
but.onclick is assigned a function so stores function in memory also sees that it accesses num so num is now closed variable that means its lifetime is increased so as to be accessed by onclick function when invoked.

Next iteration
now value of i=2,but= domelement with id = b2 now comes the function invoke,
it calls the inner function(with parameter el) with value of parameter of but(value= b2 ) .
Now inside it ,
new instance of num is assigned 2
but.onclick is assigned a function so stores function in memory also sees that it accesses num so num is now closed variable that means its lifetime is increased so as to be accessed by onclick function when invoked.
Similary all others are exectuted till the loop terminates.





相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签