Easily understand JavaScript closures

  • 2021-08-05 07:57:51
  • OfStack

Summary

Closure mechanism is the key and difficult point of JavaScript. This paper hopes to help everyone learn closure easily

1. What is a closure?

A closure is a function that can access variables in the scope of another function.

Here is a list of common closure implementations to illustrate the concept of closure with examples


function f1(){
          var n=999;
          nAdd=function(){n+=1}
          function f2(){
                alert(n);
          }
          return f2;
    }
    var result=f1();
    result(); // 999
    nAdd();
    result(); // 1000

f1 is the parent function of f2, and f2 is assigned a global variable (the value of return), which causes f2 to always be in memory, while f2 depends on f1, so f1 is always in memory, and will not be collected by garbage collection mechanism (garbage collection) after the call ends, which forms a closure.

Therefore, it can be understood as follows. The closure mechanism is that if the A function references the variable of another function B, but A does not return after B returns, it still exists. Because of the reference of A, all local variables of B will not log out with B exiting, but will exist until A logs out. At this point, A is a closure.

2. this pointer to closure

Closures are usually called in the global environment, so this usually points to window, which depends on the execution environment. In short, this points to the execution environment.

If the this of the closure is required to point to the containing object of the closure, the this of the containing object needs to be passed into the closure as a variable.

3. Notices for using closures

Because closures will make the variables in the function are stored in memory, memory consumption is very large, so we can not abuse closures, otherwise it will cause performance problems of web pages, which may lead to memory leakage in IE. The solution is to delete all local variables that are not used before exiting the function. Closures change the value of variables inside the parent function outside the parent function. Therefore, if you use the parent function as an object (object), the closure as its public method (Public Method), and the internal variables as its private properties (private value), be careful not to change the values of the internal variables of the parent function casually.

4. Solve a common interview question of closure

Question:


function onMyLoad(){
  /*
   Throw a question :
   The purpose of this question is to pop up the corresponding number subscript every time you click the corresponding target  0~4, But the reality is that no matter which target you click, a number will pop up 5
   The problem :
  arr  Every one in 1 Items  onclick  All are 1 Function instances (Function  Object ), This function instance also produces 1 Closure field ,
   This closure field refers to the variables of the outer closure field , Its  function scope  Adj.  closure  Object has an object named  i  Reference to ,
   The content of private variables in the external closure domain changes , The value obtained by the inner closure field will naturally change 
  */
  var arr = document.getElementsByTagName("p");
  for(var i = 0; i < arr.length;i++){
  arr[i].onclick = function(){
   alert(i);
  }
  }
 }

Solution

1. Add another layer of function outside, and pass i as a function parameter, so that the variables inside the function are saved every time, which is not the same memory space as the external i, and a local variable will be generated every time the function is called, so it can be guaranteed that the values saved every time do not affect each other.


for(var i = 0; i<arr.length;i++){
 arr[i].onclick = (function(arg){
  return function () {
   alert(arg);
  }
 })(i);
}

2. var i of for cycle is changed to let i with ES6 new special let, so that the current i is only valid in this cycle, so i of every cycle is actually a new variable. You may ask, if the variable i of each loop is re-declared, how does it know the value of the previous loop and calculate the value of this loop? This is because the JavaScript engine will remember the value of the previous round, and when initializing the variable i of this round, it will be calculated on the basis of the previous round.


Related articles: