JS about the closure problem in the For loop?

Source: Internet
Author: User
for (Var i=0,arr=[];i<=3;i++) {
Arr.push (function () {alert (i)});
}
Arr[0] (); // ?? The result is not 0.
ARR[1] (); // ?? It's all 4.
After conversion
for (Var i=0,arr=[];i<=3;i++) {
Arr.push (
(function (i) {
return function () {
alert (i);
}
}) (i)
);
}
The use of closures can solve the problem, why I read the first time in the code is always the last result of the I variable?
Can the great God give an analysis of the specific steps of the execution of the first piece of code?

Reply content:

To answer the question, Welcome to the Great God treatise! This is a problem with JS Pre-interpretation + scope + closuresCan be explained, in order to facilitate understanding, I use the following two diagram to illustrate:

    • This is the process before the modification:

legend: The green box for the function of the stack memory, pink for the heap memory, 0XAA memory address (the string that stores the function, and will not execute, when the function is called to execute), along the main flow from top to bottom look
In the original version before the modification, when each item in ARR executes, it goes to the upper scope to look for I, and I becomes 4 after the For loop executes, so the result of each execution in Arr is the same. In the original version before the modification, when each item in ARR executes, it goes to the upper scope to look for I, and I becomes 4 after the For loop executes, so the result of each execution in Arr is the same. function in the pre-interpretation phase, are treated as a string into the heap memory, in the actual execution, will be taken out of execution, the array is stored, in fact, only point to the heap memory pointer, I did not pass in, I was passed in the execution.


    • This is the process of running after the modification:
in the modified version, each time a new item is added in Arr, the self-executing function is executed, and I is passed as a parameter to the self-executing function, the key point is In the modified version, each time a new item is added in Arr, the self-executing function is executed, and I is passed as a parameter to the self-executing function, the key point is function (i) {...} (i) The first I is the formal parameter of the function, is a private variable, is not related to the outside I, is protected by the private scopeThe second i is the one outside of the function(That is, the first I is just a number of confusing people, you change to K is the same result, just assign I to k), so that every time the self-executing function is triggered, the current loop is equivalent to the variable i stored down. When each item in ARR executes, a function that calls a new address returned by the self-executing function is called, and the function of the new address goes to the upper scope to look for I, and the ancestor scope is the self-executing function when the new address is formed (meaning that the 0XA1 address is obtained from the first execution of the 0XAA function. 0XAA the first execution of the stack memory is the 0xa1 of the upper scope), the upper scope of I (or the parent in the scope of the parameter) is he is looking for I, so can achieve the effect you want. The mechanism for protecting private variables is closures.

As for what JS Bugs, bugs and other arguments can rest (at least the problem is not a bug). Accustomed to the automatic block of people, not to laugh at the manual block of the car clutch throttle with improper easy to stall, interesting? This is the principle of others, at least as the front-end language is still good. Do not want to pull out and industrial language a higher, I did not say.
Here's Iis a References, you just have to understand that this is not difficult to understand.

var arr = [], I; for (I = 0; I < 3; I++) {  arr.Push(function() {    Console.Log(I);  });}Console.Log(I) //3arr[0](); //3I = 5;arr[0](); //5
The key to understanding this problem is execution context, which simply means that when a function is called, it can "see" where the variable name is. In order to simplify the problem you can temporarily consider execution context only consists of the following two types: 1) global scope is the variable, 2) the variables defined in this function when each function is called.

Every time a function is called, there will be an object (called Activation object), which will include the variables and arguments defined in the call's function, along with their values. The variables for global scope are saved by the global object. when the function tries to read a variable, it reads from the nearest object (like prototyping, but notice that it depends on where the definition of the function is, not where it is executed), and it does not continue to read. Instead, you read the object in the first level context until global context。 When a function finishes executing, the object connected to it is canceled reference (then it is cleaned by GC). This means that if you have the following code:
var Globalvar = 0;var Outervar;var Innervar;Console.Log(Globalvar);Console.Log(Outervar);Console.Log(Innervar);function outer() {        function Inner() {        var Innervar = 2;        Console.Log(Globalvar);        Console.Log(Outervar);        Console.Log(Innervar);    }        var Outervar = 1;    Console.Log(Globalvar);    Console.Log(Outervar);    Console.Log(Innervar);    Inner();}outer();
about the subject:
Aside from the explanation of what we often say about execution environment scope chain variable references, we can also analyze the problem of solving problems from the perspective of some execution steps and even semantics.
for(vari=0,arr=[];i<=3;i++){    arr.push(function(){        alert(j)    });}
Because JS does not have block-level scopes
The loop body of the For loop is not a scope
Your first piece of code is equivalent to the following expansion
var arr=[];var I=0;arr.Push(function(){Console.Log(I);});I++;arr.Push(function(){Console.Log(I);});I++;arr.Push(function(){Console.Log(I);});I++;arr.Push(function(){Console.Log(I);});I++;arr[0]();arr[3]();
  • Related Article

    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.