A funny question about closures

Posted by Deemo on Sat, 04 Jan 2020 04:47:19 +0100

Because of the configuration mechanism of scope chain, the closure can only get the last value of any variable in the function. That is to say, the whole variable object is saved in the closure, not a special variable. Let's use the following example to illustrate the problem.

  function fun(){
        var result = new Array();
        //There is no problem of printing only 10 with let
        for(var i=0;i<10;i++){
            result[i] = function(){
                return i;
            }
        }
        return result;
    }
    let arr = fun();
    console.log(arr);
    console.log(arr[0]());//10
    console.log(arr[1]());//10

In this function, we assign closures directly to arrays. This function returns an array of functions. On the surface, it seems that each function should return its own index, that is, the function with bit 0 returns 0, the function with position 1 returns 1 and so on. But in fact, as in the example above, each function returns 10. Because the active objects of the fun () function are stored in the scope chain of each function, they all refer to the same variable i. When the fun() function returns, the value of variable i is 10 dead. At this time, each function references the same variable object that holds variable i. So the value of i inside each function is 10. '

But let i=0 instead of var i =0;

 function fun(){
        var result = new Array();
        //There is no problem of printing only 10 with let
        for(let i=0;i<10;i++){
            result[i] = function(){
                return i;
            }
        }
        return result;
    }
    let arr = fun();
    console.log(arr);
    console.log(arr[0]());//0
    console.log(arr[1]());//1

At this point, we can get 0-9, without creating a self executing function (anonymous function) to force the closure to behave as expected.

Of course, we can also create anonymous functions to run by themselves to achieve the desired effect.

function fun(){
        var result = new Array();
        for( var i = 0; i <10; i++){
            //First start
//            result[i] = function(num){
//                return function(){
//                    return num;
//                }
//            }(i);
            //The first kind of end
            //Second start
            (function(num){
                result[num] = function(){
                    return num;
                }
            })(i)
            //Second kinds of end
        }
        return result;
    }
    var arr = fun();
    console.log(arr);
    console.log(arr[0]());//0
    console.log(arr[1]());//1