Analysis of JavaScript scope chain, execution context and closure, analysis of javascript
Closure and scope chain are important concepts in JavaScript. I have read some documents over the past two days and summarized the relevant knowledge points as follows.
JavaScript uses lexical scoping. The scope of variables that function execution depends on is determined by the function definition, rather than the function execution. The following code snippet illustrates how to release the local variable scope in the function after calling foo (stack-based implementation, such as C language, however, from the lexical perspective, scope in the embedded anonymous function of foo should refer to the local variable scope of foo. In fact, the code running result is consistent with the lexical expression, the local scope is returned after f is called. Function object f maintains reference to the scope variable of the foo function after its main function foo is called. This is called a closure.
Var scope = 'Global scope '; function foo () {var scope = 'local scope'; return function () {return scope ;}} var f = foo (); f (); // returns "local scope"
How does a closure actually work? To understand closures, you must first understand the scope and scope of variables. Another important concept is the execution context.
Variable Scope
Global variables in JavaScript have a global scope. The scope of variables declared in the function body is the whole function body, which is local. Of course, they also include nested functions defined in the function body. The priority of local variables in the function is higher than that of global variables. If the local variables and global variables are the same, the global variables will be hidden by local variables; the priority of local variables defined in nested functions is higher than that defined in the function where nested functions are located. This is obvious, and almost everyone knows it.
Next, let's talk about what may be unfamiliar to everyone.
Function declaration escalation
One sentence is used to describe the improvement of the function declaration. It means that the variables stated in the function body are valid throughout the function. That is to say, the variable stated at the bottom of the function body will also be promoted to the top. For example:
Var scope = 'Global scope '; function foo () {console. log (scope); // "global scope" is not printed here, but "undefined" var scope = 'local scope '; console. log (scope); // apparently, print "local scope"} foo ();
The first console. log (scope) Prints undefined instead of global scope, because the Declaration of local variables has been promoted, but it has not been assigned a value.
As a property variable
In JavaScript, there are three ways to define global variables: globalVal1, globalVal2, and globalValue3 in the following sample code. An interesting phenomenon is that, in fact, the global variable is only the attribute of the global Object window/global (window in the browser and global in node. js. To better comply with the definition of common variables, JavaScript designs global variables defined with var as non-deletable Global Object Attributes. You can obtain the Object. getOwnPropertyDescriptor (this, 'globalval1'), and its retriable attribute is false.
Var globalVal1 = 1; // The global variable globalVal2 = 2 that cannot be deleted; // The global variable this. globalValue3 = 3; // same as globalValue2delete globalVal1; //> false variable not deleted delete globalVal2; // => true variable deleted delete this. globalValue3; // => the true variable is deleted.
So the question is, does the local variable defined in the function also act as the attribute of an object? The answer is yes. This object is related to function calls. In ECMAScript 3, it is called the "call object" and ECMAScript 5 as the "declaravite environment record" object. This special object is an invisible internal implementation for us.
Scope chain
From the previous section, we know that the local variables of a function can be the attributes of an invisible object. The implementation of the JavaScript lexical scope can be described as follows: each JavaScript code (Global or function) has a scope chain associated with it, which can be an array or linked list structure; each element in the scope chain defines a set of variables in the scope. When we want to find the value of variable x, find this variable from the first element of the scope chain, if not found, find the next element in the linked list until it is found or reached the end of the chain. Understanding the concept of the scope chain is essential to understanding the closure.
Execution Context
The execution of each JavaScript code segment is bound to the execution context. The Running code obtains available variables, functions, data, and other information through the execution context. The global execution context is unique and bound to the global code. each function is executed and an execution context is bound to it. JavaScript maintains the execution context through the stack data structure. The Global execution context is located at the bottom of the stack. When a function is executed, the newly created function execution context is pushed into the stack, the execution context Pointer Points to the top of the stack, and the running code can obtain the execution context bound to the currently executed function. If the function body executes nested functions, the execution context is also created and pushed to the stack. The Pointer Points to the top of the stack. After the nested function is run, the execution context bound to it is pushed to the stack, the Pointer Points to the execution context bound to the function again. Similarly, when function execution ends, the Pointer Points to the global execution context.
The execution context can be described as a data structure that contains variable objects (corresponding to the global), activity objects (corresponding to functions), scope chains, and this. When a function is executed, the activity object is created and bound to the execution context. Activity objects include variables, functions, and arguments stated in the function body. The scope chain is constructed according to the lexical scope as mentioned in the previous section. Note that this is not an activity object, and is determined at the moment when the function is executed.
The execution context is created in a specific order and stage, and different stages have different States. For details, refer to the reference materials, which will be listed at the end.
Closure
With an understanding of the scope chain and execution context, and looking back at the code at the beginning of the article, we can basically explain how the closure style works. When a function is called, the execution context created and the lexical scope chain maintain the information required by the function call. After the f function is called, the local scope can be returned.
It should be noted that multiple functions defined in a function use the same scope chain. In scenarios where the for loop is used to assign values to anonymous function objects, it is easy to cause errors. for example:
Var arr = []; for (var I = 0; I <10; I ++) {arr [I] = {func: function () {return I ;};} arr [0]. func (); // return 10 instead of 0
Arr [0]. func () returns 10 instead of 0, which is different from the sensory semantics. Before ECMAScript 6 introduced let, the scope of the variable scope was within the entire function body rather than within the code block, therefore, all the defined func functions in the above example reference the same scope chain after the for loop, the I value has changed to 10.
The correct method is as follows:
Var arr = []; for (var I = 0; I <10; I ++) {arr [I] = {func: getFunc (I )};} function getFunc (I) {return function () {return I ;}} arr [0]. func (); // returns 0
The above content introduces the knowledge of JavaScript scope chain, execution context, and closure, and hopes to help you.
Articles you may be interested in:
- In-depth analysis of js function execution environment and scope chain
- Javascript nested functions (scope chain)
- A deep understanding of JavaScript scopes and scopes
- The js bind function uses the closure to save the execution context.
- Deep understanding of the Scope Chain of the JavaScript series (14)
- Scope chains and closures in JavaScript
- Understanding and using js scopes and scope chains
- In-depth usage of Javascript Functions, recursion, and closures (execution environment, variable object, and scope chain)
- A deep understanding of the lexical scopes and scopes of JavaScript