In JavaScript, closure is a concept that is difficult to understand. The definition of closure in ECMAScript is: closure refers to the lexical representation of a function that includes variables that are not calculated. In other words, the function can use variables defined outside the function.
Do you feel more confused after reading this definition? Don't worry, let's analyze it.
A closure is a function
A closure can use variables defined outside it
The closure exists in the scope in which the variable is defined.
It seems a little clearer, but what does it mean to use variables defined outside it? Let’s first look at the variable scope.
Variables can be divided into global variables and local variables. The scope of global variables is global, and global variables can be used anywhere in js. Use the var keyword to declare a variable in a function. The variable at this time is a local variable. Its scope is only within the function where the variable is declared, and the variable cannot be accessed outside the function.
var func = function(){ var a = 'linxin'; console.log(a); // linxin}func();console.log(a); // Uncaught ReferenceError: a is not defined
Scope is relatively simple. We won’t go into details. Let’s take a look at the variable life cycle, which is closely related to closures.
Global variables, the life cycle is permanent. Local variables, when the function call that defines the variable ends, the variable will be recycled and destroyed by the garbage collection mechanism. When the function is called again, a new variable will be redefined.
var func = function(){ var a = 'linxin'; console.log(a);}func();
a is a local variable. After func is called, a will be destroyed.
var func = function(){ var a = 'linxin'; var func1 = function(){ a += ' a'; console.log(a); } return func1;}var func2 = func();func2(); // linxin afunc2(); // linxin a afunc2(); // linxin a a a
It can be seen that after the first call to func2, the variable a in func becomes 'linxin a' without being destroyed. Because func1 forms a closure at this time, the life cycle of a continues.
Now the closure is clearer.
A closure is a function, such as the func1 function above
A closure uses variables defined by other functions to prevent them from being destroyed. For example, func1 above calls the variable a
. The closure exists in the scope where the variable is defined, and the variable a exists in the scope of func, then func1 must also exist in this scope.
Now we can say that closure is the one that satisfies these three conditions.
Let’s get more familiar with closures through a simple and classic example.
for (var i = 0; i < 4; i++) { setTimeout(function () { console.log(i) }, 0) }
We may simply think that the console will print out 0 1 2 3, but in fact it prints out 4 4 4 4. Why is this? We found that the setTimeout function is asynchronous. By the time the function is executed, the for loop has ended. The value of i at this time is 4, so function() { console.log(i) } looks for variable i and can only get 4.
We remember that in the previous example, the closure saved the value of the a variable, so here we can also use the closure to save 0 1 2 3.
for (var i = 0; i < 4; i++) { (function (i) { setTimeout(function () { console.log(i) }, 0) })(i) }
When i=0, pass 0 as a parameter into the anonymous function. At this time, function(i){} the value of i in this anonymous function is 0 , wait until setTimeout is executed and follow the outer layer to find i, then you can get 0. By repeating this cycle, you can get the desired 0 1 2 3.
Calling a local variable in a closure will prevent the local variable from being destroyed in time, which is equivalent to the global variable that will always occupy memory. If you need to reclaim the memory occupied by these variables, you can manually set the variables to null.
However, in the process of using closures, it is easier to form circular references between JavaScript objects and DOM objects, which may cause memory leaks. This is because in the browser's garbage collection mechanism, if a circular reference is formed between two objects, then they cannot be recycled.
function func() { var test = document.getElementById('test'); test.onclick = function () { console.log('hello world'); } }
In the above example, a closure is created using an anonymous function in the func function. The variable test is a JavaScript object that refers to the DOM object with the id of test. The onclick attribute of the DOM object refers to the closure, and the closure can call test, thus forming a circular reference, causing both objects to be unable to be recycled. To solve this problem, just set the variable in the circular reference to null.
function func() { var test = document.getElementById('test'); test.onclick = function () { console.log('hello world'); } test = null;}
If you do not use an anonymous function to create a closure in the func function, but refer to an external function, there will be no circular reference problem.
function func() { var test = document.getElementById('test'); test.onclick = funcTest;}function funcTest(){ console.log('hello world'); }
The above is the detailed content of Detailed explanation of closures in JavaScript. For more information, please follow other related articles on the PHP Chinese website!