preface
If you are a JavaScript developer, or want to be a JavaScript developer, then you must know the internal execution mechanism of JavaScript programs. Execution context and execution stack is one of the key concepts and difficulties in JavaScript. Understanding the execution context and execution stack also helps you understand other JavaScript concepts such as promotion mechanisms, scopes, and closures. This article introduces these concepts as easily as possible.
For more quality articles please clickMaking a blog
Execution Context
1. What is execution context
In short, an execution context is an abstraction of the context in which the current JavaScript code is being parsed and executed, and any code that runs in JavaScript runs in an execution context
2. Type of execution context
There are three types of execution contexts:
- Global execution context: This is the default, most basic execution context. Code that is not in any function is in the global execution context. It does two things: 1. Creates a global object, which in the browser is the Window object. 2. Point the this pointer to the global object. Only one global execution context can exist in a program.
- Function execution context: Each time a function is called, a new execution context is created for that function. Each function has its own execution context, but is created only when the function is called. Any number of function execution contexts can exist in a program. Each time a new execution context is created, it performs a series of steps in a specific order, as discussed later in this article.
- Eval function execution context: Code running inside the Eval function also gets its own execution context, but since Eval is not commonly used by Javascript developers, it is not covered here.
The lifecycle of the execution context
The life cycle of execution context consists of three stages: create stage → execute stage → reclaim stage. This article focuses on the create stage.
1. Creation phase
When a function is called, but before any of its internal code is executed, it does three things:
- Create a variable object: first initialize the function arguments and promote the function declaration and variable declaration. More on that below.
- Scope Chain creation: During the creation phase of the execution-time context, the Scope Chain is created after the variable object. The scope chain itself contains variable objects. Scope chains are used to resolve variables. When asked to parse a variable, JavaScript always starts at the innermost layer of code nesting, and if the innermost layer doesn’t find the variable, it jumps up to the parent scope until the variable is found.
- Make sure this refers to: there are multiple cases, which are explained below
Before a JAVASCRIPT script is executed, the code must be parsed. When parsing, a global execution context is created, and variables and function declarations are extracted from the code to be executed. The variable is temporarily assigned to undefined, and the function is declared ready to use. This step is done, and then the formal execution of the procedure begins.
In addition, before a function is executed, a function execution context is created, just like the global context, except that the function execution context includes this arguments and function arguments.
2. Implementation phase
Perform variable assignment and code execution
3. Recycling phase
The execution context goes out of the stack and waits for the VM to reclaim the execution context
The details of variable promotion and this point
1. Variable declaration enhancement
Most programming languages declare variables first and then use them, but in JS things are a little different:
console.log(a)// undefined
var a = 10
Copy the code
Refer Error: A is not defined, this is because of the claim of ascending (as defined), equivalent to the following code:
var a; // Declare that the default value is undefined "ready"
console.log(a);
a=10; / / assignment
Copy the code
2. Function declaration enhancement
Function foo(){} var foo = function(){} var foo = function(){}
console.log(f1) // function f1(){}
function f1() {} // Function declaration
console.log(f2) // undefined
var f2 = function() {} // Function expression
Copy the code
Let’s use an example to illustrate this:
function test() {
foo(); // Uncaught TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
Copy the code
In the above example, foo() is called with an error, while bar is called normally.
Var foo = function(){} var foo = function(){} var foo = function(){}
In the case of bar(), the whole function is promoted so that bar() can execute smoothly.
One detail must be noted: when both functions and variables have the same name and are promoted, the function declaration takes precedence, so the variable declaration is overridden by the function declaration, but can be reassigned.
alert(a);Function a(){alert(' I am a function ')}
function a(){ alert(I'm a function.)}//
var a = 'I'm a variable';
alert(a); // Output: 'I am a variable'
Copy the code
The function declaration takes precedence over the var declaration, which means that the function declaration overrides the var declaration when two variables of the same name are declared
This code is equivalent to:
function a(){alert(I'm a function.)}
var a; //hoisting
alert(a); Function a(){alert(' I am a function ')}
a = 'I'm a variable';/ / assignment
alert(a); // Output: 'I am a variable'
Copy the code
Finally, let’s look at a more complicated example:
function test(arg){
// 1. Arg is "hi"
// 2. Function declaration takes precedence over variable declaration, so arg is function
console.log(arg);
var arg = 'hello'; Var arg variable declaration is ignored and arg = 'hello' is executed
function arg(){
console.log('hello world')}console.log(arg);
}
test('hi');
Function arg(){console.log('hello world')} hello */
Copy the code
This is because when a function executes, it first forms a new private scope and then follows the following steps:
- If the parameter is tangible, the parameter is assigned first
- For private scope preinterpretation, function declarations take precedence over variable declarations, which are eventually overwritten by the former, but can be reassigned
- Code in private scopes executes from top to bottom
3. Determine the direction of this
It is important to understand that the value of this is checked at execution time, not at definition. Why? Because this is part of the execution context, and the execution context needs to be determined before the code is executed, not when it is defined. Here’s an example:
Function foo() {console.log(this.a) //1} var a = 1 foo() {console.log(this); } var obj={fn:fn}; obj.fn(); Function CreateJsPerson(name,age){function CreateJsPerson(name,age){ //=>p1.name=name this.age=age; //=>p1.age=age} var p1=new CreateJsPerson(" 下 载 ",48); Function add(c, d){return this.a + this.b + c + d; } var o = {a:1, b:3}; add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 add.apply(o, [10, 20]); <button id="btn1"> This </button> <script type="text/javascript"> let btn1 = document.getElementById('btn1'); let obj = { name: 'kobe', age: 39, getName: function () { btn1.onclick = () => { console.log(this); //obj }; }}; obj.getName(); </script>Copy the code
Let’s explain each of these cases one by one
- For calling foo directly, no matter where foo is placed, this must be window, right
- For obj.foo(), we just need to remember that whoever called the function is this, so this in the foo function is the obj object in this scenario
- In the constructor pattern, the occurrence of this. XXX = XXX in the class (in the function body) is an instance of the current class
- Call, apply, and bind: this is the first argument
- The arrow function this points to: the arrow function does not have its own this. If it does, this of the outer function is the this of the inner arrow function. If not, this is the window.
Execution Context Stack
Each time a function is called, a new execution context is created. How do you manage the creation of so many execution contexts?
The JavaScript engine creates an execution context stack to manage the execution context. The execution context stack can be thought of as a stack structure for storing function calls, following the principle of first in, last out.
From the above flow chart, we need to remember a few key points:
- JavaScript executes on a single thread and all code is queued.
- When the browser executes global code, it first creates the global execution context, pushing it to the top of the execution stack.
- Each time a function is executed, the execution context of the function is created and pushed to the top of the stack. After the execution of the current function completes, the execution context of the current function goes off the stack and waits for garbage collection.
- The browser’s JS execution engine always accesses the execution context at the top of the stack.
- There is only one global context, which is pushed out when the browser closes.
Let’s look at another example:
var color = 'blue';
function changeColor() {
var anotherColor = 'red';
function swapColors() {
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
}
swapColors();
}
changeColor();
Copy the code
The above code runs as follows:
- When the code is loaded in the browser, the JavaScript engine creates a global execution context and pushes it onto the current execution stack
- When a changeColor function is called, the js execution engine immediately creates a changeColor execution context (EC for short) and pushes this execution context into the execution stack (ECStack for short).
- The swapColors function is called during the execution of changeColor. Similarly, an execution context for swapColors is created and pushed onto the execution stack before the execution of the swapColors function.
- When the swapColors function completes, the execution context of the swapColors function is removed from the stack and destroyed.
- When the changeColor function completes, the execution context of the changeColor function is removed from the stack and destroyed.
To recommend a good BUG monitoring toolFundebug, welcome free trial!
Welcome to pay attention to the public number: front-end craftsmen, we will witness your growth together! If you feel rewarded, you are welcome to give me a tip to encourage me to export more quality open source content
Refer to the article
- Understand the execution context of JavaScript
- The way of the front-end interview
- An in-depth understanding of javascript archetypes and closure families
- Understand Javascript execution context and execution stack
- In-depth understanding of scope and context in JavaScript
- Front End Basics (II) : Detailed diagram of execution context
- Deep understanding of declarations of promotion, scope (chain) and JS
this
The keyword