What are the solutions to the effects of closures when JavaScript loops add events?

Source: Internet
Author: User
Tags variable scope
A solution to this problem on the Internet is to borrow a layer of functions to avoid problems.
/ http blog.csdn.net/victorn/a rticle/details/3899261
But it's still hard to understand. Is there any other way to understand and solve it?
Update: I hastily set a layer of functions okay, and I dodged.

Reply content:

Very happy to have a pure JS problem.
1, @ Yang CoffeeIt is not true that the value of JS is not transmitted. There are two ways to pass a parameter in JS: By value and by sharing.
Like C,c++,java, the way they pass the argument is By value and by reference. The former is the pass value, the latter is the transmission address. And JS is the same, the former is a value, the latter is the transmission address.
By value is for raw data types such as Int,char, while by sharing and by reference are for advanced data structures such as object,struct. We can imagine that an object or struct cannot be passed only by passing a value.
A simple example illustrates the difference between by reference and by sharing.
var bar;
var foo = bar;
bar = {' key ': ' Value '};
console.log (foo, bar);
By sharing foo is undefined, bar is {' key ': ' Value '}, and by reference should both be {' key ': ' Value '}.

2. In fact, LZ to understand this problem, to understand the scope of JS (scope).
When each function is created, he has 3 important built-in properties (property) that are also created at the same time.
{
AO//record variables, parameters and other information in function
This //is the This at the time of the call to this.xx
Scope//A chain that points to the outer function AO (which may be implemented by an array when implemented).
}
JS, we often talk about SCOPE is actually this: Scope=ao+scope.
To return to the problem of closures:
If we write this program like this:
For (var i =0; i
Link[i].onclick = function () {alert (i);}; Inner function

}
The scope for which you can get inner function is this:

{
AO
This //equals link[i]
Scope//The record of the window, including the variable i we need
}
The For loop executes immediately, so when the onclick trigger, the inner function looks for the variable i, it is found in the Ao+scope, not in the AO, and the variable I in scope has become the link.length.

Write this program using what everyone says about closures:
//here is the window scope
for (var i =0; i

Link[i].onclick = (function (i) {//outer function
return function () {//inner function
alert (i);
};
}) (i);

}
to analyze the scope of the inner function:
{
AO//No important infomation
This //We don't care it.
scope//outer function and window scope
}
scope of the outer function
{
AO//contains parameter I
This //don ' t care it.
Scope//window scope.
}


At this point, if the inner function is triggered, he will look for the variable i from his AO and scope (outer function's AO and window scope). You can see that I is already contained in the AO of the outer function, and for this for loop, there is a pair of n ( function () {}) ()is created to execute. So each inner function has a specific outer function that contains the variable i.

This will smooth out the 0,1,2,3 ...

Conclusion: We can see that closures are actually caused by scope, so, broadly speaking, all functions are closures.


In addition, this also contains, This , function expression and function DeclarationThe difference, here is not a talk.

3. Another approach:
Using the bubble feature of the Dom onclick event, which is @Xiiiiiin said to get an agent.

The onclick event listener is defined on the parent node of the link DOM node. The parameter is E (other names are also possible, but have parameters). So we can know through the e.target that the child node is the click, can also do the corresponding processing.
This is a better approach. (closures can sometimes produce memory leaks).

Probably say so much, still have to go to work. Hope to be useful to LZ. If anything is wrong, please criticize me. I think the best way is to solve it by wrapping a layer of functions.

The original
Alink.onclick = function () {alert (i)};
Change to:
(function (i) {Alink.onclick = function () {alert (i)};}) (i);

I think this is the best way, JS only function will be divided into the scope (and python a bit like), If/else, for loop will not divide the scope, so the original way six times the loop refers to the same variable I, because the closure is bound to the function.
Now that a layer has been wrapped, I is passed to the inner layer of the anonymous function local scope, so that the six loops will establish a separate I (because it is six different scopes). It's hard to understand your question without reading that article.
You put the parameters in it:
Alink.onclick = (function (i) {
return function () {
alert (i);
};
}) (i);


In addition I do not like the OnXxx attribute.




PS: It is difficult to use Rich text editor to get me to post code, in addition, the second part of the answer to the nth disappear.

This is related to the way in which the JS function is passed and how the event is assigned.
1. js function the transfer parameter is the value of the passOf
2, the value of the onclick should give a function Declaration, when the event is triggered only one event parameter is passedto the declared function.

If Alink[i].onclick = function () {alert (i) is used in the loop;
I was not the parameter of this anonymous function, it was passed in, and when the onclick event was triggered, the loop was over, I was the last value.
If you declare a function ( I) {alert (i);}
Then this I refers to the event, when the event is triggered will only pop up the trigger name.

While using Alink[i].onclick = (function (_i) {return function () {alert (_i);} }) (i);
Here is the execution anonymous function for outer layerreturn This anonymous function of the inner layerPassed to the onclick.
Note here the outer function is immediately executed, with a parameter, we passed it to it, not the event trigger.
the inner layer function is without parameters, when the event executes, the trigger passes it an event value.
An anonymous function is generated for each i in the loop, and I is the value of the parameter for the generated anonymous function.
Equivalent to When i = 2 in the loop, a function is generated: function () {alert (2);}; Assigned to the Alink[2].onclick, i.e. Alink[2].onclick = function () {alert (2);};
That's what we want.

PS: Closures are just a gimmick, not the core of the problem.
This technique is equivalent to the following method, and the following does not use closures.
var al = function (param) {
return function () {
alert (param);
}
}
Alink[i].onlick = Al (i) in the loop;Uh...... This example, more in favor of the variable scope of the problem to rethink the problem, it is the key to understand the scope of JavaScript variables and scope chain, the previous answer seems to have not been explained clearly.

This question is mentioned in the javascript:the good Parts, see this example:
Bad EXAMPLE
var addactions = function (nodes) {
for (var i = 0; i < nodes.length; i++) {
Nodes[i].onclick = function (e) {
alert (i);
};
}
};
END Bad EXAMPLE

The explanation is this:
the intent of the function is to give each event processor a different I. But it failed to achieve the purpose because the event handler function binds the I itself, not the value of the variable I at the time the function was constructed.


The reason is this, see "javascript:the Definitive Guide" will understand:
All JavaScript functions are closures: they are objects and are associated to the scope chain. Each time a JavaScript function is called, a new object is created to hold the local variable, and the object is added to the scope chain (simply understood: the scope chain is the object list).
In this bad example, function (e) {alert (i);} Are all defined in the same function call, so they share the variable i. That is to say, I is the same in their scope chain. That is, the scope chain associated to the closure is "active".

"Javascript:the good Parts" Of course also gives the solution:
var addactions = function (nodes) {
var helper = function (i) {
return function (e) {
alert (i);
};
};

for (var i = 0; i < nodes.length; i++) {
Nodes[i].onclick = Helper (i);
}
};

Explanation: Create a helper function outside of the loop instead of creating a function in a loop. Look at this article, it's all clear. JavaScript execution context Here I think the first answer is too obscure, the average person can not understand.
Here I come up with a more interesting conjecture,
————————————————————————————————————————
Paste the code
http://www. W3.org/tr/xhtml1/dtd/xh TML1-TRANSITIONAL.DTD ">
http://www. w3.org/1999/xhtml ">


<title>Untitled Document</title>













————————————————————————————————————
As you can see, the index buffer value is the method that most people use, this is a very reliable way, but very few people could say why, but with the so-called professional to let you confused.

————————————————————————————————————
Actually, this is occasionally see the garbage collection mechanism, the number of references to the conjecture,
Under normal circumstances, if you use Var y=i and then continue to reference in return FN, you can only refer to the last value, because most of the time, 0,1,2 ... these serial numbers will only be saved by one variable, and you will never expect to save them again with another variable .
but now we use Y to quote again, to make it 2 times,So the so-called cross-scope does not exist, and we can refer to each value.
————————————————————————————
Of course, this is only a conjecture, but here has been verified, as to whether to continue, but also to continue to investigate. Be an agent.
The loop adds the attribute for each node and then binds an event to the outer elem.
No need to shut the bag. Very professional answer, know inside answer technical question so professional ... Great
  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.