The introduction
On the Internet a lot of articles about the scope and closures, their understanding of the pure theoretical knowledge is not quickly, but his pictures have very strong memory and comprehension, so decided to show the knowledge of the knowledge point to the picture, deepen their understanding and if you can help to the children’s shoes are studying is the better
Let me tell you about this in terms of the entire life cycle of a function
Function life cycle
Let’s start with some sample code
var a = 10;
function func(a) {
var a = 20;
a++;
console.log(a);
}
func();
console.log(a);
Copy the code
Before executing the program
-
First, create an ECS, which is an array that holds the execution environment of the function being called, or an object.
-
Then add main, the execution environment for the browser’s main program, to the ECS
-
Create the global scope object Window
-
The main execution environment references window
When you define a function
-
Global variables of primitive types are stored directly in the Window environment. Since functions are reference types, global variables are first declared by function names
-
The function object is then created to encapsulate the function definition
-
The scope attribute of a function object refers to the scope in which the function was created. This means that when a function is executed, it will go back to the scope in which it was created to find the variable if the function itself does not provide enough variables for the function to execute completely.
-
The function name is followed by an address to the function object
Reference types can only store addresses, which are explained in detail in this note on value passing
Function call
-
Push the execution environment element for this function call into the ECS
-
Create the function scope object (AO) used in this function call, which is the temporary scope
-
Create and store all local variables in the AO, including parameters and variables declared with var in functions
-
Set the PARENT property of the AO and the scope property of the reference function to point to the parent scope object
-
The execution environment of the function refers to the AO
-
Follow the arrow, look for variables in the AO, local variables, if not in the AO, then follow the arrow to the parent scope
After the function call
The execution environment of the function is removed from the stack, the AO is released, and local variables in the AO are also released.
When we learned the whole result, it became clear that the results of the two consoles would also agree.
closure
As mentioned earlier, global variables are reusable but pollute the world, while local variables do not pollute the world but are not reusable.
I personally think of closures as a mechanism for reusing variables and protecting them from contamination, which is a solution to this situation.
The characteristics of
The outer function that wraps the protected variable and the inner function that operates on the variable
The outer function returns the object of the inner function
return function(){.. }
- Assign an inner to a global variable directly
function
- Store internal functions in an object’s property or array element
return [function function function]
或return {fun:function(){... }}
Call the outer function, enclosing the returned inner function object with the outer variable, forming a closure.
The principle of
Post the sample code first
function outer() {
var num = 1;
return function() {
console.log(num++);
};
}
var getNum = outer();
getNum();
getNum();
num = 1;
getNum();
Copy the code
Let me draw the principle of closure formation using the drawing tool
The outer name is stored in the window and refers to the outer function object. GetNum also stores the variable name in the window because it was declared in advance.
GetNum = outer() creates outer and assigns getNum.
Var num = 1; var num = 1; , all have said before, but many repeat.
Create an anonymous function, getNum points to an anonymous function object, and the scope of the anonymous object points to its parent scope, outer’s scope. The Outer’s AO should have left as well, but because of the powerful triangle, it was forced to hold it back, creating what is called a closure.
The reason for closures is that the outer function’s scoped object cannot be released
GetNum =outer()getNum is just a function
Calling getNum() creates a temporary scope for getNum. GetNum is an anonymous function in outer, so its parent points to the scope left by outer. When console.log(num++) is executed and num is not in his scope, he follows the chain of scopes and finds num in outer’s scope and autoappends it. So the next time getNum is called num will start at 2, not 1.
Num is not a global variable, and we implement repeated calls to num. That’s what closures are for.
Setting num = 1 simply adds the value of num to the window object, The next time getNum is called, the js engine will start from getNum scope and search for num along the scope chain. The outerAO will find num, so num in the window will not be affected at all. So the output of this code is 1, 2, 3.
disadvantages
Closures do have their drawbacks, of course
-
It takes up more memory than normal functions because the scoped object (AO) of the outer function always exists
-
Prone to memory leaks
The solution
Reset external variables that reference in-memory function objects to NULL
getNum = null;
Copy the code
The getNum line to outer will break, the triangulation will break, and both the function object and outerAO will be destroyed.
If you think the article is good, please give a star to encourage gayhub