Understanding of javascript closures

  • 2020-05-24 05:13:43
  • OfStack

1. First of all, we need to know the variable scope chain

There are two types of scope for variables: global variables and local variables. Variables that are not defined into any function are global variables, and variables defined in the function are local variables. Note that when defining variables within a function, 1 must use the var keyword, and variables without the var keyword are global variables.

Each piece of code in javascript has a scope chain associated with it, which is a list of objects or a linked list that defines the variables in the "scope" of the code. The scope of the top-level code consists of global variables. A scope chain that does not contain nested functions has two objects: one for defined function parameters and local variables, and one for global variables. The scope chain of nested functions has three objects: function parameters and local variables -- parameters of external functions and local variables -- global variables. Functions can access objects in the scope chain, so that functions can access global variables, and vice versa, that is, local variables inside functions cannot be accessed outside functions.


var a=1;
function wai(){
  alert(a);        
  var m=10;
  n=20;
}

wai();          //=> 1;  Global variables can be accessed inside functions 
alert(m);        //=> error;  The external access function local variable reports an error   
alert(n);        //=> 20;  The variables defined inside the function are not used var Keyword, so it's a global variable that can be accessed externally 

2. How to read local variables externally

Sometimes, we need to access the local variables of the function's inner board from the outside, so we need to use a flexible method to achieve this. We take advantage of the javascript variable scope to define child functions within the function, so that the child functions can access the variables in the parent function


function wai(){
 var m=10;
  function nei(){
    alert(m); 
 }
  return nei;
}

var f = wai();
nei();              //=> error; nei() The function is 1 Three local variables that cannot be accessed externally 
f();               //=> 10;

3, closures

The function nei() in the last code is a closure. It can be seen from the above that a closure is a function that can read local variables inside a function, is a function defined to the inside of a function, and can essentially be considered as a bridge connecting the inside of a function and the outside of a function to 1.

Closures do two things:

1 is the variable that reads inside the function mentioned earlier

2 is can let these local variables save in memory, the realization of variable data sharing


function wai(){
  var m=99;
  function nei(){
    alert(m);
    m++;
  }
  return nei;
}
      
var f= wai();
f();         //=> 99;
f();         //=> 100;
f();         //=> 101;

When the wai() function is running, the variable m is saved in memory, and f() can read m's value, but alert(m) cannot!

We can also pass arguments to a closure function, as shown in the example below, which defines an anonymous function and returns a closure function that adds the incoming arguments to the local variable i in the anonymous function and makes i self-incrementing.


var wai=(function(){
  var i=0;
  return function(num){
    num+=i;
    alert(num);
    i++;
 }
})();
wai(1);//1
wai(2);//3
wai(3);//5

To get a deeper understanding of closures, let's look at one example:

Now I want to define a function that returns an array, and each element of the array is a function, and each function will pop up its index value

We might write it like this


function box(){
 var arr=[];
  for(i=0;i<5;i++){
    arr[i]=function(){return i;}
  }
 return arr;  
}
var a=box();
alert(a);        //=> contains 5 An array of function bodies 
alert(a[0]());     //=> 5;
alert(a[1]());    //=> 5;

This is because i is also a local variable in memory. When we run a[0](), the value of i is already 5. The value of i is constantly increasing during the operation of the box() function.

Solution: implementation of closures


function box(){
var arr=[];
    for(var i=0;i<5;i++){

         arr[i]=(function(num){
           return function(){return num;}
         })(i);

     }
return arr;     
}

var arr=box();

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

  alert(arr[i]());//0,1,2,3,4
}

4. Precautions for using closures

1) since closures will save variables in functions in memory, which consumes a lot of memory, closures should not be abused, otherwise they will cause performance problems of web pages, which may lead to memory leaks in IE. The solution is to remove all unused local variables before exiting the function.

2) the closure will change the value of the variables inside the parent function outside the parent function. So if you use the parent function as an object (object), the closure as its public method (Public Method), and the internal variable as its private property (private value), be careful not to change the value of the parent function.

5. Here are a few thoughts on closures

If you can understand the results of the following code, you should be able to understand how closures work.

Js code


var name = "The Window"; 
var object = { 
  name : "My Object", 
  getNameFunc : function(){ 
    return function(){ 
      return this.name;       //=> Of nested functions this Is a global variable or undefined You don't inherit the parent function this
    }; 
  } 
}; 
alert(object.getNameFunc()()); //The Window

The reason why the above output is "The window" is that this does not inherit the parent function this in nested functions, and its value is global variable or undefined(ECMAScript5 below), so it returns the name variable of the global object. To return the name property of object, the code is as follows:


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

The above code assigns this of the parent function object to the cur variable, and its nested functions can access its properties through the cur variable

------------------------------------------------------------------------------------------------------
The JavaScript closure example


function outerFun()
{
var a=0;
function innerFun()
{
a++;
alert(a);
} 
}
innerFun();  //=>error

The code above is incorrect.innerFun() is scoped inside outerFun(), and it is incorrect to call it outside outerFun().

Change it to the following, which is the closure:

Js code


function outerFun()
{
   var a=0;
  function innerFun()
  {
    a++;
    alert(a);
  }
  return innerFun; // Note that there 
}
var obj=outerFun();
obj(); // The results for 1
obj(); // The results for 2
var obj2=outerFun();
obj2(); // The results for 1
obj2(); // The results for 2

What is a closure:

When an internal function is referenced outside of the scope in which it is defined, the closure of the internal function is created. If the internal function references variables located in the external function, these variables will not be freed in memory when the external function is called, because the closure requires them.

--------------------------------------------------------------------------------------------------------

Let's do another example

Js code


function wai(){
 var m=10;
  function nei(){
    alert(m); 
 }
  return nei;
}

var f = wai();
nei();              //=> error; nei() The function is 1 Three local variables that cannot be accessed externally 
f();               //=> 10;
0

The result is 0,4. Because the var keyword is used inside the function to maintain the a scope inside outFun().

Take a look at the following code:

Js code


function wai(){
 var m=10;
  function nei(){
    alert(m); 
 }
  return nei;
}

var f = wai();
nei();              //=> error; nei() The function is 1 Three local variables that cannot be accessed externally 
f();               //=> 10;
1

It turns out to be 0,0 which is weird, why is that ?

Scope chain is a term that describes a path along which the value of a variable can be determined. When a=0 is executed, since the var keyword is not used, the assignment will follow the scope chain to var a=4; And change its value.


Related articles: