This article mainly introduces the Closure (Closure) in JavaScript, the scope chain of the function call object and variable, and what is the Closure, and provides examples, if you need it, you can refer to the closure as an important feature of JavaScript. its biggest function is to save information during function operation. In JavaScript, many features of closures are derived from the scope chain in the function call process.
Scope chain of function call objects and variables
For every callback function call in JavaScript, JavaScript creates a local object to store the local variables defined in the function. if there is a nested function inside the function ), javaScript then defines a nested local object on the defined local object. For a function, the number of layers of nested function definitions is also the number of layers of nested local objects. This local object is called a "function call object" ("call object" in ECMAScript 3, and ECMAScript 5 is renamed as "declarative environment record ", but I personally think it is easier to understand the name in ECMAScript 3 ). Take the following function call as an example:
The code is as follows:
Function f (x ){
Var a = 10;
Return a * x;
}
Console. log (f (6); // 60
In this simple example, when calling the f () function, JavaScript will create a call object for the f () function (called f_invokeObj). There are two attributes inside the f_invokeObj object: a and x; when running f (), the value of a is 10 and the value of x is 6. Therefore, the final returned result is 60. The figure is as follows:
When function nesting exists, JavaScript creates multiple function call objects:
The code is as follows:
Function f (x ){
Var a = 10;
Return a * g (x );
Function g (B ){
Return B * B;
}
}
Console. log (f (6); // 360
In this example, when calling the f () function, JavaScript will create a calling object (f_invokeObj) for the f () function, which has two internal attributes a and x, when running f (), JavaScript parses and defines the g () function in f () function and creates g () the calling object (g_invokeObj) has an internal attribute B. The value of B is 6 same as the input parameter x, so the final returned result is 360. The figure is as follows:
As you can see, function call objects form a chain. When the nested function g () is running and the variable value needs to be obtained, the search starts from the most recent function call object. if the search fails, then, the function calls the object chain to search for further called objects. this is the so-called "variable scope chain ". If the two function call objects contain the same variables, the function will take the variable value in the call object closest to itself:
The code is as follows:
Function f (x ){
Var a = 10;
Return a * g (x );
Function g (B ){
Var a = 1;
Return B *;
}
}
Console. log (f (6); // 360, not 3600
In the preceding example, variable a and a have different values in the call object (g_invokeObj) of the g () function and the call object (f_invokeObj) of the f () function, when running the g () function, the value used inside the g () function is 1, and the value used outside the g () function is 10. The following figure shows the function call object chain:
What is a closure?
All functions in JavaScript are objects. when defining a function, a function call object chain is generated. the functions define a function call object chain. As long as the function object exists, the corresponding function call object exists. Once a function is no longer used, the corresponding function call object will be reclaimed; this one-to-one combination between function objects and function call object chains is called a closure ". In the above examples of f () and g () functions, there are two closures: f () function object and f_invokeObj object constitute a closure, while g () the function object and the g_invokeObj-f_invokeObj object chain form the second closure together. After the g () function is executed, the g () closure is garbage collected because the g () function is no longer used. after that, after the f () function is executed, for the same reason, the f () closure is also recycled.
From the definition of closures, we can conclude that all JavaScript functions are closures after definition-because all functions are objects, all functions have their corresponding call object chains after execution.
However, what makes closures really work is nested functions. Because embedded functions are defined only when external functions are running, the values of variables stored in the closure of embedded functions (especially the local values of external functions) is the value in this running process. As long as the embedded function object still exists, its closure still exists (the variable value in the closure will not change), thus saving the information of the function running process. Consider the following example:
The code is as follows:
Var a = "outside ";
Function f (){
Var a = "inside ";
Function g () {return ;}
Return g;
}
Var result = f ();
Console. log (result (); // inside
In this example, when the f () function is run, the g () function is defined and the closure of the g () function is created at the same time, the g () closure contains the g_invokeObj-f_invokeObj object chain, therefore, the value of variable a during f () function execution is saved. When console. when a log () statement is run, the g () closure still exists because the g function object still exists. when the g function object still exists, javaScript uses the g () closure that still exists and obtains the value ("inside") of variable a from it ").