The application of closure in loop

Keywords: Javascript

The application of closure in loop

for(var i=1; i<=5; i++){
    setTimeout( function timer(){
        let temp = new Date();
        console.log(i + "----" + temp.toLocaleTimeString() + "." + temp.getMilliseconds());
    }, i*1000);
    
    if(i == 5){
        var now = new Date();
        console.log("for Loop end----"+now.toLocaleTimeString() + "." + now.getMilliseconds());
    }
}

// End of for cycle - 7:51:29.885 PM
// 6 ---- 7:51:30.885 PM
// 6 ---- 7:51:31.885 PM
// 6 ---- 7:51:32.885 PM
// 6 ---- 7:51:33.885 PM
// 6 ---- 7:51:34.885 PM

The callback of the delay function will be executed at the end of the loop;
In fact, when the timer is running, even if setTime(..., 0) is not executed in the iteration, many callback functions will still be executed after the end of the loop, so 6 will be output each time

for (var i = 0; i <= 5; i++){
    (function(){
        setTimeout(function timer(){
           let temp = new Date();
           console.log(i + "----" + temp.toLocaleTimeString() + "." + temp.getMilliseconds());
        }, i*1000)
    })();
    
    if(i == 5){
        var now = new Date();
        console.log("for Loop end----"+now.toLocaleTimeString() + "." + now.getMilliseconds());
    }
}
for (var i = 0; i <= 5; i++){
    (function(){
        var j = i; // IIFE has its own variables
        setTimeout(function timer(){
            let temp = new Date();
            console.log(j + "----" + temp.toLocaleTimeString() + "." + temp.getMilliseconds());
        }, j*1000)
    })();
    
    if(i == 5){
        var now = new Date();
        console.log("for Loop end----"+now.toLocaleTimeString() + "." + now.getMilliseconds());
    }
}
// End of for cycle - 8:14:28.915 PM
// 0 ---- 8:14:28.916 PM
// 1 ---- 8:14:29.916 PM
// 2 ---- 8:14:30.916 PM
// 3 ---- 8:14:31.916 PM
// 4 ---- 8:14:32.916 PM
// 5 ---- 8:14:33.916 PM

Improvement 1: using immediate execution function (IIFE)

The immediate execution function is used to generate a new scope for each iteration, so that the callback of delay function can close the new scope in each iteration;

for (var i = 0; i <= 5; i++){
    (function(j){
        setTimeout(function timer(){
            let temp = new Date();
            console.log(j + "----" + temp.toLocaleTimeString() + "." + temp.getMilliseconds());
        }, j*1000)
    })(i);
}

Improvement 2: use setTimeout to pass parameters to callback function to generate timer's closure to for loop scope

Using the delay function to pass parameters to its callback function, a new scope is generated for the callback in each iteration, so that the callback of the delay function can close the new scope in each iteration;

for (var i = 0; i <= 5; i++){
    setTimeout(function timer(j){
        let temp = new Date();
        console.log(j + "----" + temp.toLocaleTimeString() + "." + temp.getMilliseconds());
    }, i*1000, i);
}

Posted by Sir Mildred Pierce on Mon, 09 Dec 2019 04:53:17 -0800