The concept and usage notes of JavaScript closures

JavaScript closures

A closure is a function that can read variables inside other functions , because in JS, only sub-functions inside a function can read local variables. If you want to have limited access to variables in another function within a function, you can use closures. Closures are used to solve this requirement. The essence of closures is to create another function within a function. **A closure can be simply understood as "a function defined inside a function", and a closure is a bridge connecting the inside of the function with the outside of the function.

Closures have 3 characteristics:

① Function nested function

②The parameters and variables outside the function can be referenced inside the function

③Parameters and variables will not be recycled by the garbage collection mechanism

Use of closures:

1. By calling the closure function externally, the variables inside the function can be accessed outside the function

2. Make the variable object in the function context that has finished running remain in memory , because the closure function retains the reference of this variable object, so this variable object will not be recycled

 function f1(){
    
    
    var n=999;
    nAdd=function(){
    
    n+=1}
    function f2(){
    
    
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
  nAdd();
  result(); // 1000
//在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。
//为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后被垃圾回收机制(garbage collection)回收。
//这段代码中另一个值得注意的地方,就是"nAdd=function(){n+=1}"这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

Form 1 of closure: function as return value

function a(){
    
    
    var name = 'zhangsan'
    return function(){
    
    
        return name;
    }
}
var b = a()
console.log(b)//zhangsan

In this code, the return value in a() is an anonymous function. This function is inside the scope of a(), so it can get the value of the variable name under the scope of a(), and assign this value as the return value to the variable b under the global scope, so that the value of the variable in the local variable can be obtained under the global variable.

There is one thing to note here. When declaring variables inside a function, you must use the var command. If you don't use it, you're effectively declaring a global variable!
function fn(){
    
    
    var num = 1;//fn()外部函数访问不到n
    return function(){
    
    
        var n = 0;//匿名函数内部可以访问num
        //既然匿名函数可以读取fn中的局部变量,那么只要把匿名函数作为fn的返回值,就可以在fn外部读取它的内部变量了!
        console.log(++n);
        console.log(++num);
    }
}

var fn1 = fn();
fn1();// 1 2
fn1();// 1 3 函数执行结束后,num变量继续保留在内存中。
fn1();// 1 4 函数执行结束后,num变量继续保留在内存中。

In the above code, the return value in fn() is an anonymous function, and this anonymous function is assigned to fn1 , because when a function is executed, the function and the variables in it will be destroyed. In the anonymous function, the variable num in fn() is accessed, so the variable num will not be destroyed, and after the execution of fn1(), both fn1() and the variable n inside will be destroyed, leaving only the variable num in the memory, which realizes that the variable remains in the memory after the function execution ends.

The second form of closure: the closure is passed as a parameter

Finally, summarize the advantages and disadvantages of closures

benefit

①Protect the safety of variables in the function, realize encapsulation, and prevent variables from flowing into other environments to cause naming conflicts

②Maintain a variable in memory, which can be used as a cache (but using too much is also a disadvantage, consuming memory)

③ Anonymous self-executing functions can reduce memory consumption

harm

① One of the points has been reflected above, that is, the referenced private variable cannot be destroyed, which increases memory consumption and causes memory leaks. The solution is to manually assign null to the variable after using it;

② Secondly, because the closure involves cross-domain access, it will cause performance loss. We can reduce the impact on execution speed by storing cross-scope variables in local variables and then directly accessing local variables.

Notes on using closures

1) Because the closure will make the variables in the function be stored in the memory, the memory consumption is very large, so the closure cannot be abused, otherwise it will cause performance problems of the web page, and may cause memory leaks in IE. The solution is to delete all unused local variables before exiting the function.

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

thinking questions

If you can understand the running results of the following two pieces of code, you should understand the operation mechanism of closures.

Code snippet one:

var name = "The Window";
  var object = {
    
    
    name : "My Object",
    getNameFunc : function(){
    
    
      return function(){
    
    
        return this.name;
      };
    }
  };
  alert(object.getNameFunc()());//The Window
//this默认指向Window对象,所以最终输出的结果是全局对象的name,也就是"The Window"

Code snippet two:

 var name = "The Window";
 var object = {
    
    
    name : "My Object",
    getNameFunc : function(){
    
    
      var that = this;
      return function(){
    
    
        return that.name;
      };
    }
  };
  alert(object.getNameFunc()());//My Object
//这里的this一开始默认指向的是Window对象,然后var that=this把全局变量变成了局部变量,object.getNameFunc()返回的结果是that.name,也就是局部变量"My Object"

Guess you like

Origin blog.csdn.net/m0_48895748/article/details/127047140