preface
With the continuous influx of knowledge, the degree of refinement and depth of knowledge foundation becomes particularly important. Whether you are a beginner or have been working for a few years. The foundation is often the foundation of new technology learning and understanding, but the depth of knowledge to a certain extent, the learning of new knowledge more quickly, understanding will be more thorough!
so
A programmer’s career lasts about ten years, a tenth of a human lifespan. The front-end project is just a part of your life and work, but you are all of it. You are his soul. Stop playing games for long hours and playing games at work. Study more to accompany your project in the most perfect state!
The body of the
This is the word count, this is very important, please don’t go away!
knowledge
- Js run trilogy
- What is precompilation
- Precompiled tetralogy
- What is an execution context
- How to create implementation above
Js run trilogy
- Analysis of grammar
- precompiled
- Explain to perform
Analysis of grammar
- Word Segmentation/Lexical Analysis (Tokenizing/Lexing)
- Parsing/Parsing
- Code generation
In the process of compiling a traditional language, a piece of source code in a program goes through three steps, collectively called “coding,” before it is executed. Let me explain it briefly
Stage 1: This process breaks down a string of characters into blocks of code that make sense (to the programming language), called lexical units (tokens). For example, consider the program var a = 2; . The program is usually broken down into the following lexical units: var, a, =, 2; . Whether Spaces are considered lexical units depends on whether they make sense in the language.
Stage 2: This process converts a stream of lexical units (arrays) into a hierarchical nested tree of elements that represents the program’s syntactic structure. This Tree is called the Abstract Syntax Tree (AST).
Stage 3: The process of turning the AST into executable code is called code generation.
But Javascript is a little different. First, Javascript engines don’t have as much time to optimize as compilers in other languages do, because unlike other languages, Javascript compilation doesn’t happen before build. Simply put, any snippet of JavaScript code has to be compiled before it can be executed (which is usually precompiled just before it can be executed). Therefore, the JavaScript compiler first evaluates var a = 2; The program compiles, is ready to execute, and usually executes immediately.
What is precompilation?
JavaScript snippets are compiled before they are executed (which is usually precompiled just before they are executed). That says enough bullshit, let’s move on to the next stage
Precompiled tetralogy
- Creating an AO Object
- Find the parameter and variable declarations and use the variable and parameter names as AO property names with the value undefined
- Unify argument values and parameters
- Find the function declaration inside the function body and assign the value to the function body
The AO above is Active scope, GOGlobal scope, in the execution context, you only need to know it is an object! strong
I’ll explain it to you in code
var a = 1
function text(a){
c = 0
var c;
console.log(c)
a = 3
var b = 2
console.log(b)
functon b(){}
functon d(){
var d = 5
}
d()
console.log(b)
}
text(1)
// After 4 steps of precompilation:
// GO:{
// a :undefind
// text:functon text(a){}
/ /}
// text AO:{
// a:1
// c:undefind
// b:function b(){}
// d:function d(){}
// [[scope]] :{
// 0:text AO
// 1:GO
/ /}
// }
/ /}
// d AO:{
// d:undefind
// [[scope]] :{
// 0:d AO
// 1:text AO
// 2:GO
// }
/ /}
// Execute the code line by line...
Copy the code
Is pretty simple….
Next look at…. below
What is an execution context?
In short, an execution context is an abstraction of the context in which JavaScript code is evaluated and executed. Whenever Javascript code is running, it is running in an execution context.
The type of execution context
There are three types of execution context in JavaScript.
- Global execution context— This is the default or base context, and any code that is not inside a function is in the global context. It does two things: create a global Window object (in the case of the browser) and set it
this
Is equal to the global object. There is only one global execution context in a program. - Function execution Context – Each time a function is called, a new context is created for that function. Each function has its own execution context, but is created when the function is called. There can be any number of function contexts. Each time a new execution context is created, it performs a series of steps in a defined order (discussed later).
- The Eval function executes the context– perform in
eval
The code inside a function also has its own execution context, which JavaScript developers don’t often useeval
So I won’t talk about it here.
Execution stack
An execution stack, or “call stack” in other programming languages, is a stack with LIFO (LIFO) data structures that are used to store all execution contexts created while the code is running.
When the JavaScript engine first encounters your script, it creates a global execution context and pushes it onto the current execution stack. Every time the engine encounters a function call, it creates a new execution context for that function and pushes it to the top of the stack.
The engine executes functions whose execution context is at the top of the stack. When the function completes execution, the execution context pops out of the stack and the control flow moves to the next context in the current stack.
Let’s take a look at the following code example:
let a = 'Hello World! '; function first() { console.log('Inside first function'); second(); console.log('Again inside first function'); } function second() { console.log('Inside second function'); } first(); console.log('Inside Global Execution Context');Copy the code
The execution context stack of the above code.
When the above code loads in the browser, the JavaScript engine creates a global execution context and pushes it onto the current execution stack. When the first() function call is encountered, the JavaScript engine creates a new execution context for the function and pushes it to the top of the current execution stack.
When second() is called from within the first() function, the JavaScript engine creates a new execution context for the second() function and pushes it to the top of the current execution stack. When second() completes, its execution context is popped off the current stack and the control flow moves to the next execution context, that of the first() function.
When first() completes, its execution context pops off the stack and the control flow reaches the global execution context. Once all code has been executed, the JavaScript engine removes the global execution context from the current stack.
How do I create an execution context?
Now that we’ve looked at how JavaScript manages execution contexts, let’s look at how the JavaScript engine creates execution contexts.
There are two phases to creating an execution context: 1) the creation phase and 2) the execution phase.
The Creation Phase
Before the JavaScript code executes, the execution context goes through the creation phase. Three things happen during the creation phase:
- The determination of the this value, known as the This binding.
- Create the lexical environment component.
- Create the variable environment component.
So the execution context is conceptually expressed as follows:
ExecutionContext = { ThisBinding = <this value>, LexicalEnvironment = { ... }, VariableEnvironment = { ... }},Copy the code
This binding:
In the context of global execution, the value of this points to a global object. In browsers, this refers to the Window object.
In the context of function execution, the value of this depends on how the function is called. If it is called by a reference object, this is set to that object, otherwise this is set to global or undefined (in strict mode). Such as:
let foo = { baz: function() { console.log(this); } } foo.baz(); // 'this' refers to 'foo' because 'baz' is called by // object 'foo' let bar = foo.baz; bar(); // 'this' points to the global window object because // no reference object is specifiedCopy the code
Lexical environment
The official ES6 documentation defines the lexical environment as
A lexical environment is a canonical type that defines the associations of identifiers and concrete variables and functions based on the lexical nesting structure of ECMAScript code. A lexical environment consists of an environment logger and a null value that may reference an external lexical environment.
Simply put, a lexical environment is a structure that holds identity-variable mappings. (The identifier here refers to the name of the variable/function, and the variable is a reference to the actual object [containing the object of the function type] or the original data).
Now, inside the lexical environment there are two components :(1) the environment logger and (2) a reference to the external environment.
- The environment logger is the actual location where variable and function declarations are stored.
- A reference to an external environment means that it has access to its parent lexical environment (scope).
There are two types of lexical environments:
- The global environment(in the context of global execution) is a lexical environment that has no references to the external environment. The external environment reference for the global environment isnull. It has built-in Object/Array/ etc., prototype functions in the environment logger (associated with global objects such as window objects) and any user-defined global variables, and
this
The value points to the global object. - In a function environment, user-defined variables within a function are stored in the environment logger. And the referenced external environment may be the global environment, or any external function that contains this internal function.
Environment loggers also come in two types (as above!) :
- Declarative environment loggers store variables, functions, and parameters.
- The object environment logger is used to define the relationship between variables and functions that appear in the global context.
In short,
- In a global environment, the environment logger is the object environment logger.
- In a functional environment, the environment logger is the declarative environment logger.
Note – For function environments, the declarative environment logger also contains a arguments object passed to the function (which stores the index and parameter mapping) and the length of the argument passed to the function.
Abstractly, the lexical environment in pseudocode looks like this:
GlobalExectionContext = {LexicalEnvironment: {EnvironmentRecord: {Type: "Object", // bind identifier here} outer: <null> } } FunctionExectionContext = { LexicalEnvironment: { EnvironmentRecord: { Type: } outer: <Global or outer function environment reference>}}Copy the code
Variable environment:
It is also a lexical environment whose environment logger holds bindings created in the execution context of variable declaration statements.
As mentioned above, the variable environment is also a lexical environment, so it has all the attributes of the lexical environment defined above.
In ES6, one difference between a lexical environment component and a variable environment is that the former is used to store function declarations and variable (let and const) bindings, while the latter is used only to store var variable bindings.
Let’s look at sample code to understand the above concepts:
let a = 20;
const b = 30;
var c;
function multiply(e, f) {
var g = 20;
return e * f * g;
}
c = multiply(20, 30);
Copy the code
The execution context looks like this:
GlobalExectionContext = { ThisBinding: <Global Object>, LexicalEnvironment: { EnvironmentRecord: { Type: A: < uninitialized >, b: < uninitialized >, multiply: < func >} outer: <null>}, VariableEnvironment: {EnvironmentRecord: {Type: "Object", // bind identifier c: undefined,} outer: <null> } } FunctionExectionContext = { ThisBinding: <Global Object>, LexicalEnvironment: { EnvironmentRecord: { Type: "Declarative", // bindings identifiers: {0:20, 1:30, length: 2},}, outer: <GlobalLexicalEnvironment>}, VariableEnvironment: {EnvironmentRecord: {Type: "Declarative", undefined }, outer: <GlobalLexicalEnvironment> } }Copy the code
Note – The function execution context is created only if the multiply function is called.
You may have noticed that the let and const variables are not associated with any value, but the var variable is set to undefined.
This is because during the creation phase, the engine examines the code for variable and function declarations, which are stored entirely in the environment but are initially set to undefined (in the case of var) or uninitialized (in the case of let and const).
This is why you can access variables defined by var (albeit undefined) before declaration, but access let and const variables before declaration will get a reference error.
This is what we call variable declaration enhancement.
Execution phase
This is the easiest part of the whole article. At this stage, all of these variables are allocated and the code is executed.
Note – at execution time, if the JavaScript engine cannot find the value of the let variable at the actual location declared in the source code, it will be assigned the value of undefined.
conclusion
-
The global execution context creation stage is divided into three steps: bind this, create lexical environment -> handle let and const, variable environment -> handle var define initial value undefind,
-
In the execution stage, when the function is defined, there is a [[scope]] object pointing to the scope Chain in the AO of the function. In the pre-compilation stage, the three steps of global GO are also executed (the decomposed four steps can also be remembered).
-
When a function is defined, bit 0 of the Scope Chain is used to point to the global GO context object. At the moment before the function call is executed, which is the precompilation stage, bit 0 of the Scope Chain points to its OWN AO function context object, and bit 1 points to the global GO context, and the Scope Chain is generated.
reference
JavaScript execution context – Execution stack