Loops and Closures

Use javascript a lot at work, but don't understand what closures are? I always feel that this language has its hidden side. If you can master it, it will greatly increase the kilometers.

Closures are a natural result of writing code based on lexical scope. In fact, closures can be seen everywhere in commonly written js code.

A closure occurs when a function can remember and access the lexical scope it is in, even if the function executes outside the current lexical scope

PS: My understanding of it is that when a piece of lexical scope code is executed, the js engine will recycle it to improve performance, but the closure prevents this recycling, so that this lexical scope is still in memory Among them, when you call a local variable in the lexical scope, it still exists.

Let's take a look at a piece of code that clearly shows the closure:

function foo(){

    var a = 2;

    function bar(){

        console.log(a);

    }

    return bar;

}

var baz = foo();

baz(); //2 ----This is the effect of the closure

After foo() is executed, the entire inner scope of foo() is usually expected to be destroyed, because we know that the engine has a garbage collector to free memory space that is no longer used. Since it appears that the contents of foo() will never be used again, it is natural to consider recycling it. The "magic" thing about closures is that they prevent this from happening. In fact the inner scope still exists, so it is not recycled.

function wait(message) {

    setTimeout( function timer() {

        console.log( message );

    }, 1000 );

}

wait( "Hello, closure!" );

After wait(..) executes for 1000 milliseconds, its inner scope does not disappear, and the timer function still retains the closure of the wait(..) scope.

To illustrate closures, a for loop is the most common example.

for (var i=1; i<=5; i++) {

     setTimeout( function timer() { console.log( i );

    }, i*1000 );

}

Normally, we would expect the behavior of this code to output numbers 1 to 5, one per second, one at a time.

But in reality, this code will output 6 five times at a rate of one per second when it runs.

In fact, when the timer is running, even if setTimeout(.., 0) is executed in each iteration, all callback functions will still be executed after the loop ends, so it will output a 6 each time.

The correct way is that we want to use closures. First, according to the definition, we have to give each loop a lexical scope, and each scope must have its own value of i, as follows:

for(var i =1; i<=5;i++){

    (function(i){ //Give each loop a separate lexical scope

        setTimeout(function(){

            console.log(i);

        },i*1000);

    })(i);

}

Of course in ES6, you can use the let statement:

for (let i=1; i<=5; i++) {

     setTimeout( function timer() {

        console.log( i );

    }, i*1000 );

}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325527678&siteId=291194637