This is the fourth day of my participation in the August More text Challenge. For details, see: August More Text Challenge

In MDN, a function is bound with a reference to its surrounding environment (i.e., the function is surrounded by references), and such a combination is called a closure. That is, closures allow you to access the scope of an inner function from within its outer function.

A closure is a function that has access to variables in the scope of another function. The most common way to create a closure is to create another function within a function that has access to variables local to the current function.

Closures are used primarily to design private methods and variables. The advantage of closure is that it can avoid the pollution of global variables. The disadvantage is that the closure will be resident in memory, which will increase the memory usage. Improper use is easy to cause memory leakage. In JS, functions are closures, and only functions have the concept of scope

Closures have three features:

  1. Function nested function
  2. Functions can refer to external parameters and variables from within
  3. Parameters and variables are not collected by the F garbage collection mechanism

Closures have two common uses.

  1. Make us inThe variables inside the function can be accessed from outside the function. By using closures, we can access variables inside the function externally by calling the closure function externally. We can use this method to create private variables.
  2. Keeps variable objects in the context of a function that has finished running in memoryBecause the closure function retains a reference to the variable object, the variable object is not reclaimed.

The nature of closures is a special application of scope chains. Once you know how to create a scope chain, you can understand how closures are implemented.

Code sample

Create a closure

In the inner function, we can access the variable a through the scope chain, so this constitutes a closure because a is a variable in the scope of the other function.

function outer(){
    var a = 1;
    function inner(){
        console.log(a);
    }
    inner(); / / 1
}
outer();
Copy the code

Print 1,2,3,4 every second using closures

// Print five fives
for( var i = 0; i < 5; i++ ) {
    setTimeout(() = > {
        console.log( i );
    }, 1000)}// Use closures
for (var i = 0; i < 5; i++) {
    (function (i) {
        setTimeout(function() {
            console.log(i);
        }, i * 1000);
    })(i)
}

// Use the let block-level scope
for(let i = 0; i < 5; i++){
    setTimeout(function() {
        console.log(i);
    }, i * 1000);
}
Copy the code

Understand the following code and you’ll understand how closures work

Code 1


function makeAdder(x) {
    return function(y) {
        return x + y;
    };
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2)); / / 7
console.log(add10(2)); / / 12
Copy the code

Code 2


function f1(){
    var n=999;

    nAdd=function(){n+=1}

    function f2(){
      alert(n);
    }
    return f2;
}

var result=f1();
result(); / / 999
nAdd();
result(); / / 1000
Copy the code

Result is actually the closure f2 function. It runs twice, the first time with a value of 999 and the second time with a value of 1000. This proves that the local variable n in function F1 is always kept in memory and is not automatically cleared after a call to f1.

Why is that? The reason is that f1 is the parent function of F2, and F2 is assigned to a global variable, so F2 is always in memory, and f2’s existence depends on F1, so F1 is always in memory, and it is not collected by garbage collection after the call ends.

Another interesting thing to note in this code is that the line nAdd=function(){n+=1} is not preceded by the var keyword, so nAdd is a global variable, not a local one. Second, the value of nAdd is an anonymous function, which is itself a closure, so nAdd acts as a setter that can operate on local variables inside the function from outside.

Code 3


 var name = "The Window";varobject = {name : "My Object".getNameFunc : function(){return function(){return this.name; }; }}; alert(object.getNameFunc()());//"The Window"

Copy the code

The this object is bound at runtime based on the execution environment of the function. In global functions, this equals window, and when the function is called as a method of an object, this equals that object. However, the environment in which anonymous functions are executed is global. When each function is called, its active object automatically takes two special variables: this and arguments. The inner function searches for these two variables only as far as its live object, so it is never possible to directly access these two variables in the outer function.


var name = "The Window";varobject = {name: "My Object".getNameFunc: function() {
        var that = this;return function() {
            returnThat. The name; }; }}; alert(object.getNameFunc()());//"My Object"

Copy the code

Before we define the anonymous function, we assign the this object to a variable called that, and after we define the closure, the closure can also access this variable, because it is a variable that we deliberately declared in the enclosing function. Even after the function returns, that still refers to object, so calling object.getNameFunc()() returns “My object “. (This and Arguments have the same problem. If you want to access the arguments object in scope, you must store the reference to that object in a variable that can be accessed by another closure.)

Code 3

function outerFun(){
    var a=0;
    function innerFun(){
        a++;
        alert(a);
    }
    return innerFun; // Notice here
}

var obj=outerFun();

obj(); // The result is 1

obj(); // The result is 2

var obj2=outerFun();

obj2(); // The result is 1

obj2(); // The result is 2

Copy the code

Code 5


function outerFun(){
    / / not var
    a =0;

    alert(a);
}

var a=4;

outerFun(); / / 0

alert(a); / / 0

Copy the code

A scope chain is a term describing a path along which the values of variables can be determined. When a=0, because the var keyword is not used, the assignment chain goes to var a=4; And change its value.

Code 6


function a() {
    var i = 0;
    function b() { alert(++i); }
    return b;
}

var c = a();
c(); / / 1
c() / / 2
Copy the code