As a front end white, I don’t know if you have the same problem as me. After reading the analysis of an interview question, I thought I could at that time, but I couldn’t look again two days later. Blindly pursuing all kinds of new technology, I feel like I can do everything, but I can’t do it once I get started… After reflecting on the pain, I finally realized the problem and began to focus on the training of basic skills. Nearly half a year to read through (in fact is swallowed) “JavaScript Advanced Programming”, “You don’t know JavaScript on, in, under” and other books, this series of articles is my reading process of knowledge points in some summary. Like the students remember to help me point 😁.
Understand wang series (1) thoroughly understand JavaScript function execution mechanism understand Wang series (2) thoroughly understand JavaScript scope understand Wang series (3) thoroughly understand JavaScript objects understand Wang series (4) thoroughly understand JavaScript classes To understand this, we need to understand JavaScript data types. To understand this, we need to understand JavaScript data types Complete JavaScript type conversion
When Javascript code executes, different variables are stored in different locations in memory: in the heap and in the stack. There are objects in the heap. The stack holds basic type variables and Pointers to objects. But what we mean by execution stack is a little different.
In this stack, in addition to executing code, the values of the underlying types are stored in the stack, and the reference types are stored in the heap.
Null does not open up memory, but points the previous pointer to the null pointer. Null and undefined: null wants to assign a value, but has not yet assigned a value; null and undefined: has not assigned a value
When executing an executable script, js will first create a global executable context. When executing a function call, js will create an execution context EC. Of course, an executable may have many function calls, so many ECS are created, so the JavaScript engine creates an Execution contextstack (ECS) to manage the Execution context.
When the function call completes, js exits the execution environment and destroys it, returning to the previous method’s execution environment… This process is repeated until all the code in the execution stack is executed. Here are the keywords above. Let’s analyze them at once:
Execution Context Stack
Activation of a GlobalContext Variable Object
There can be two stages of function execution: function establishment stage and function execution stage
1. Function creation phase
A create execution context object is created when a function is called without executing the code inside the function
fn.EC = {
variableObject: // Arguments and local members in the function
scopeChains: // The active object in the parent scope of the current function
this: {} // The current function inside this point
}
Copy the code
The build phase did three things:
[[scope]] = the variable object VO/AO in the context EC
Here, the variable object VO is a special object related to the execution context, used to store the context’s function declarations, function parameters, and variables. VO is divided into global context variable object VO, function context variable object VO
VO(globalContext) === global;
Let’s take the following function as an example:
var a = 10;
function test(x) {
var b = 20;
};
test(30);
// Global context variable object
VO(globalContext) = {
a: 10.test: <reference to function>}; VO(test functionContext) = {x: 30, b: 20};Copy the code
2. Function execution phase
fn.EC = {
activationObject: // Arguments and local members in the function
scopeChains: // The active object in the parent scope of the current function
this: {} // The current function inside this point
}
Copy the code
The function execution phase changes the variable object VO into the active object AO by doing the following:
- Create a new execution, context EC (compressed to execute in ECStack)
- Initializes the pointing to THIS
- [[scopeChain]] : XXX
- Create an AO variable object to store variables
Here’s a quick look at the steps for storing variables:
- Find the parameter and variable declaration (variable promotion) and use the variable and parameter names as AO attribute names with undefined values
- Unify argument values and parameters
- Find the function declaration in the function body, and assign the value to the function body
Here’s an example:
function fn(a) {
console.log(a);
var a = 123;
console.log(a);
function a() {}
console.log(a);
var b = function() {}
console.log(b);
function d() {}
}
fn(1);
Copy the code
Storing variable procedures:
/ / 1
AO: {
a: undefined.b: undefined
}
/ / 2
AO: {
a: 1.b: undefined
}
/ / 3
AO: {
a: function a() {},
b: undefined
d: function d() {}}Copy the code
Note:
- Function promotion takes precedence over variable promotion
- When the declared function name is re-var, but not yet assigned, the variable still refers to the function
Now let’s take a formal look at AO
// 1. In the context of function execution, VO is not directly accessible, so the active object plays the role of VO.
// 2.Arguments object. This object contains the following properties: callee, length
// 3. Internally defined functions
// 4. The corresponding variable environment on the binding;
// 5. Internally defined variables
VO(functionContext) === AO;
function test(a, b) {
var c = 10;
function d() {}
var e = function _e() {};
(function x() {});
}
test(10); // call
// When the context of the test function with parameter 10 is entered, the AO behaves as follows:
// AO does not contain function "x". This is because "x" is a FunctionExpression (FE for short) and not a function declaration, and function expressions do not affect VO
AO(test) = {
a: 10.b: undefined.c: undefined.d: <reference to FunctionDeclaration "d">
e: undefined
};
Copy the code
3. Complete process analysis
Let’s take the following code as an example to complete the function execution:
let x = 1;
function A(y) {
let x = 2;
function B(z) {
console.log(x + y + z);
}
return B;
}
let C = A(2);
C(3);
Copy the code
Function execution process simulation:
*/ ECStack = [//=> global execution context EC(G) = {//=> global variable object VO(G): {... / / = > contains the global object of original attributes x = 1; A = function (y) {...}; A [[scope]] = VO (G); / / = > create functions when they determine the scope}}]; / * the second step: perform function A (2) * / ECStack = [/ / = > A execution context of EC (A) = {/ / = > list initialized: AO - > VO (G) (A) [scope] : VO scopeChain (G) : "AO (A), A [[scope]] > / = > create functions A live objects AO (A) : {the arguments: [0, 2), y: 2, x: 2, B: Function (z) {...}, B = [[scope]] AO (A); this: window;}}, / / = > global execution context EC (G) = {/ / = > global variable object VO (G) : {... / / = > contains the global object of original attributes x = 1; A = function (y) {...}; A [[scope]] = VO (G); / / = > create functions when they determine the scope}}]; */ ECStack = [//=> EC(B) {[scope]: AO(A) scopeChain: "AO (B), AO (A), B [[scope]] > / = > create the active object function B AO (B) : {the arguments: [0, 3], z: 3, this: Window;}}, / / = > A execution context of EC (A) = {/ / = > list initialized: AO - > VO (G) (A) [scope] : VO scopeChain (G) : "AO (A), A [[scope]] > / = > create functions A live objects AO (A) : {the arguments: [0, 2), y: 2, x: 2, B: Function (z) {...}, B = [[scope]] AO (A); this: window;}}, / / = > global execution context EC (G) = {/ / = > global variable object VO (G) : {... / / = > contains the global object of original attributes x = 1; A = function (y) {...}; A [[scope]] = VO (G); / / = > create functions when they determine the scope}}]Copy the code
4. Scope chains
Every javascript function is an object. There are some properties in the object that we can access and some that we can’t. These properties are only accessible by the javascript engine, and [[Scope]] is one of them. [[scope]] refers to what we call a scope, where the set of run-time contexts is stored.
Scope chain: A collection of execution context objects stored in [[scope]] that are chained. This is called a scope chain.
When a function executes, it creates its own AO at the top of the scope (0), so it looks for variables from the top of the scope chain down
Let’s take a look at the scope chain of a function as an example
function a() {
function b() {
var b = 234;
}
var a=123;
b();
}
var glob = 100 ;
a();
Copy the code
So let’s change the code,
function a() {
function b() {
var b = 234;
}
var a=123;
return b
}
var glob = 100 ;
let b = a();
b()
Copy the code
When we return function b, we find that when function A finishes executing, a’s AO is broken, but B retains its reference to it. So A’s AO was not destroyed. This is a closure. It is a closure that meets two conditions:
- Fn external has a reference to internal
- Local members of the FN scope are accessed in another scope
5. this
The this object is bound at runtime based on the execution environment of the function, which is equal to window in a global function and equal to that object when the function is called as a method of that object.
Each function automatically takes two special variables when it is called :this and arguments. The internal function searches for these two variables only as far as their live object, so it is never possible to directly access these two variables in the external function.
6. Describe the execution process of EventLoop
- The entire script is initially executed as a macro task
- In the process of execution, the synchronous code is executed directly, the macro task enters the macro task queue, and the micro task enters the micro task queue
- After the macro task is executed, exit the queue. Check the list of microtasks and execute them in sequence until all the microtasks are executed
- Perform rendering for the browser UI thread
- Check whether there is a Web Worker task and execute it if there is
- When this round of macro tasks is completed, go back to 2 and loop until both the macro and microtask queues are empty