xTable of Contents [1] illustration [2] description [3] Summing up the previous words
In this paper, we analyze closures from the perspective of execution environment, first with a diagram, and then according to the diagram content of the code line by row, trying to explain the closure more intuitively
Icon
Description
The following is a detailed description of the diagram in the order in which the code executes the flow
function foo () { var a = 2; function Bar () { console.log (a); } return Bar;} var baz = foo (); Baz ();
The "1" code execution stream goes into the global execution environment, and the code in the global execution environment enters the declaration elevation (hoisting)
The "2" execution stream executes the 9th line of code var baz = foo (), LHS query for a, assign the Baz function foo ()
The "3" execution flow continues to execute the 9th line of code var baz = foo (), and calls the Foo () function, at which point the execution stream enters the Foo () function execution Environment, declaring the promotion process for the code in the execution environment. There are two execution environments in the execution environment stack, and the Foo () function is the execution environment where the current execution flow resides
The "4" execution stream executes the 2nd line of code var a = 2;a LHS query for a assigns a value of 2
The "5" execution stream executes the 7th line of code return bar, and the bar () function is returned as the return value. Supposedly, when the Foo () function has been executed, it should destroy its execution environment and wait for the garbage to be collected. But because its return value is the bar function. There is a free variable A in the bar function that needs to find the value of variable A in the execution environment of the scope chain to the Foo () function, so the Foo () function cannot be destroyed, only from the active state to the inactive state, and the global execution environment becomes the active state.
The "6" execution stream executes the 10th line of code Baz (), and Baz holds the return value bar of the Foo () function by looking for the Baz value in the global execution environment. So executing baz () will call the bar () function, at which point the execution flow enters the bar () function execution environment and declares the promotion process for the code in the execution environment. There are three execution environments in the execution environment stack, where the bar () function is the execution environment for the current execution flow
During the declaration of Ascension, because A is a free variable, it needs to be looked up through the global scope of the Bar () (), the scope chain bar (), and finally finds var a = 2in the Foo () function, which is the 2nd line of code, and then foo () A value of 2 is found in the execution environment of the function, so assign a value of 2
The "7" execution stream executes line 7th of code Console.log (a), invokes the internal object console, and passes the A as a parameter into the console object from the log method. Finding the value of a in the execution environment of the bar () function is 2, so the final display in the console is 2
"8" execution stream executes the 6th line of code }, the execution Environment of Bar () is ejected execution environment stack, and is destroyed, waiting for garbage collection, control is returned to the global execution environment
"9" When the page is closed, all execution environments are destroyed
Summarize
As can be seen from the 5th step of the above note, because of the closure bar () function, the execution environment of its parent function foo () is always present in memory, in order to make it possible to invoke the bar () function, the parent function foo () can be accessed through the scope chain, and the value of variables stored in its execution environment is obtained. Until the page closes, the execution environment of the Foo () function is destroyed with the global execution environment to free up memory space
Because closures occupy memory space, use closures sparingly. Try to remove the reference as soon as possible after using the closure, so that the memory is freed earlier
// dereference by placing Baz as null function foo () { var a = 2; function Bar () { console.log (a); // 2 } return bar;} var baz = foo (); Baz (); NULL ; /* subsequent code */
In-depth understanding closure series The second article--from the implementation of environmental perspective closures