There are concepts such as Scope (scope), Scope chain (scope chain), Execute context (execution context), Active Object (active object), Dynamic Scope (dynamic scope), and Closure (closure) in JavaScript. To understand these concepts, we analyze them from two aspects: static and dynamic.
First we write a simple function as an example:
We define an add function with two formal parameters.
Static aspect:
When creating the add function, the Javascript engine will create the Scope chain of the add function. This scope chain points to the Global Context. If it is expressed graphically as shown below:
As can be seen from the above figure, when the add function is created, the scope chain has already been created. Therefore, we can draw a conclusion that the scope chain of the function has been created when the function is created, rather than dynamically. runtime. Let's take a look at what happens during dynamic runtime.
Dynamic aspects:
When the add function is executed, JavaScript will create an Execute context, which contains all the information needed during the runtime of the add function. Execute context also has its own Scope chain. When the function runs, the JavaScript engine will first initialize the scope chain of the execution context from the scope chain of the add function, and then the JavaScript engine will create an Active Object, which contains All local variables, parameters, and this and other variables during function runtime.
If you vividly describe what happens during the dynamic runtime of the add function, you can use the following figure to describe it:
As can be seen from the above figure, the execution context is a dynamic concept. It is created when the function is run. At the same time, the Active Object object is also a dynamic concept. It is referenced by the scope chain of the execution context. Therefore, we can draw a conclusion: execution context and active objects are both dynamic concepts, and the scope chain of the execution context is initialized by the function scope chain.
The above mentioned function scope and execution context scope. Next, let’s talk about the issue of dynamic scope. When using the with statement, the catch clause of try-catch, and the eval method in JavaScript, the JavaScript engine will Dynamically change the scope of the execution context. Let’s take a look at it through an example:
When the above initUI function is executed, JavaScript will dynamically create a scope corresponding to the with statement and place it at the front end of the execution context scope chain. The above process can be vividly described through the following figure. The area marked in red in the figure below is displayed. The scope generated by the with statement.
Finally, let’s take a look at the most mysterious Closure in JavaScript. Closure in JavaScript is actually a function. Closure is created during the runtime of the function. Let’s take a look at an example below:
When the assignEvents function above is executed, a closure will be created, and this closure will refer to the id variable in the assignEvents scope. If you follow the traditional programming language approach, id is a variable stored on the stack. When The id disappears after the function is executed, so how can it be referenced again? Obviously JavaScript takes another approach here. Let's take a look at how JavaScript implements closures. When the assignEvents function is executed, the JavaScript engine will create a scope chain of the assignEvents function execution context. This scope chain contains the active object when assignEvents is executed. At the same time, the JavaScript engine will also create a closure, and the scope of the closure The chain will also refer to the active object when assignEvent is executed, so that when assignEvents is executed, although the scope chain of its own execution context no longer refers to the active object, the closure still refers to the active object corresponding to assignEvents runtime. This This explains the closure mechanism inside JavaScipt. The following figure can be used to vividly describe the situation during the runtime of the assignEvents function above:
As can be seen from the above, after the assignEvents function is executed, document.getElementById("save-btn").onclick references the closure, so that when the user clicks save-btn, the execution of the closure will be triggered. , then let’s take a look at the situation when the closure is executed. As mentioned earlier, closures in JavaScript are actually functions, so the situation when the closure is executed is the same as when the function is executed. The following figure vividly describes the closure associated with the above onclick event.
As can be seen from the above figure, the JavaScript engine first creates the execution context of the closure, then uses the closure scope chain to initialize the execution context scope chain of the closure, and finally places the corresponding active object when the closure is executed. Entering the front end of the scope further verifies the assertion that closures are functions.