In this article, I will go into the execution context, the most basic part of JavaScript ). After reading this article, you should be clear about what the interpreter has done, why functions and variables can be used before declaration, and how their values are determined. What is the execution context? When JavaScript code is run, the execution environment is very important. There are several different situations: Global Code-the default environment where your code is first executed. Function Code-each time a function is entered. Eval code -- when the eval internal text is executed. You can read many scope resources online. The purpose of this article is to make things easier, let's think of the term execution context as the Environment/scope of the currently executed code. I have mentioned enough. Now let's look at a code example that contains global and function context. In a simple example, we have a global context circled by a purple border and three different function contexts framed by green, blue, and orange respectively. Only the global context (variable) can be accessed by any other context. You can have multiple function contexts. Each time you call a function to create a new context, a private scope is created. No variable declared in the function can be directly accessed outside the current function scope. In the preceding example, a function can access the variable declaration outside the current context, but cannot access the internal variable/function declaration in the external context. Why is this happening? How is the code interpreted? The JavaScript interpreter in the execution context stack browser is implemented as a single thread. This means that only one thing can happen at a time. Other texts or events will be placed in a queue called the execution stack. The following figure shows the abstract view of a single-thread Stack: as we know, when the browser loads your script for the first time, it enters the global execution context by default. If you call a function in your global code, the time sequence of your program will enter the called function and wear a new execution context, and press the newly created context to the top of the execution stack. If you call other functions in the current function, the same thing will happen here. The code execution flow enters the internal function, creates a new execution context, and pushes it to the top of the execution stack. The browser will always execute the execution context at the top of the stack. Once the execution of the current context function ends, it will be popped up from the top of the stack and the context control will be handed over to the current stack. The following example shows the execution stack call process of recursive functions: copy the code (function foo (I) {if (I = 3) {return ;} else {foo (++ I) ;}} (0); copy the Code. This Code calls itself three times, and add one to the I value each time. Each time the foo function is called, a new execution context is created. Once the context is executed, it is popped up from the top of the stack and the control is returned to the following context until only the global context is available. There are five key points to remember: execution stack (call stack): single thread. Synchronous execution. A global context. Unlimited function context. Each time a function is called, a new execution context is created, including the call itself. We now know the details of the execution context that a new execution context will be created if a function is called once. However, within the JavaScript interpreter, the execution context of each call is divided into two phases: the creation phase [before the function is called but no internal code is executed ]: create a Scope Chain to create variables, functions, and parameters. Evaluate the value of "this. Activation/code execution phase: Assign variable values and function references to explain/execute code. Each execution context can be abstracted into an object with three attributes: executionContextObj = {scopeChain: {/* variable object (variableObject) + variable object of all parent execution contexts */}, variableObject: {/* function arguments/parameter, internal variables and function declaration */}, this: {} activate/variable object [AO/VO] When the function is called, executionContextObj is created, but before the actual function is executed. This is the first stage and creation stage we mentioned above. In this phase, the interpreter scans the parameters or arguments passed to the function, the local function declaration and the local variable declaration, and creates the executionContextObj object. The scan result completes the creation of variable objects. Here is a pseudo-overview of how the interpreter evaluates the code: Find the code that calls the function. Create an execution context before executing the function code. Enter the creation stage: Initialize the scope chain: create variable object: Create an arguments object, check the context, initialize the parameter name and value, and create a reference copy. Function declaration for scanning context: creates an attribute on the variable object for each detected function, specifically the function name, which has a reference pointing to the function in memory. If the function name already exists, the reference pointer will be overwritten. The variable Declaration in the context of the scan: For each detected variable declaration, create an attribute on the variable object-that is, the variable name, initialize the value of the variable to undefined. If the variable name already exists in the variable object, no operation will be performed and the scan will continue. Obtain the value of "this" in the context. Activation/code execution phase: Run/interpret the function code in the current context, and assign the variable value as the code line is executed. Let's take an example: copy the code function foo (I) {var a = 'hello'; var B = function privateB () {}; function c () {} foo (22); copy the code. When foo (22) is called, The creation status is as follows: copy the code fooExecutionContext = {scopeChain :{...}, variableObject: {arguments: {0: 22, length: 1}, I: 22, c: pointer to function c () a: undefined, B: undefined}, this: {...}} copy the code as you can see, the creation status is responsible for processing the name of the defined attribute, not assigning specific values to them, and processing the form parameter/real parameter. Once the creation stage is complete, the execution flow enters the function and the activation/code execution stage. After the function execution is complete, copy the code fooExecutionContext = {scopeChain :{...}, variableObject: {arguments: {0: 22, length: 1}, I: 22, c: pointer to function c () a: 'hello', B: pointer to function privateB ()}, this :{...}} copy code upgrade (Hoisting) You can find a lot of resources on the Internet that define JavaScript hoisting terms, and interpret variables and function declarations to the top of the function scope. However, no one explains why this happens, and learns the previous new knowledge about how the interpreter creates an activity object that loves you. It's easy to understand why. See the following example: copy the code (function () {console. log (typeof foo); // function pointer console. log (typeof bar); // undefined var foo = 'hello', bar = function () {return 'World' ;}; function foo () {return 'hello' ;}} (); copy the code to answer the following question: why can we access it before foo declaration? If we follow the creation phase, we know that the variable has been created in the activation/code execution phase. So before the function is executed, foo has been defined in the activity object. Foo is declared twice. Why is foo displayed as a function instead of undefined or string? Although foo is declared twice, we know that the function has been created in the active object in the creation phase. This process occurs before the variable is created, if the property name already exists on the active object, we only update the reference. Therefore, the reference to the foo () function is first created in the active object. When we interpret var foo, we can see that the foo attribute name already exists, so the Code does not do anything and continues to be executed. Why is the bar value undefined? Bar is actually a variable, but the value of the variable is a function, and we know that the variables are created during the creation stage but they are initialized to undefined. To sum up, I hope you now know how the JavaScript interpreter executes your code. Understanding the execution context and stack helps you understand the reasons behind it-why your code is interpreted as different values from what you originally wanted. Do you want to know that the internal operation overhead of the interpreter is too large, or the necessity of your JavaScript knowledge? Know that the execution context helps you write better JavaScript? You want to know how the interpreter works internally. It takes too much space and necessary JavaScript knowledge. Knowing the execution context can help you write better JavaScript code. Note: Some people have been asking about closures, callbacks, latencies, and other issues. I will mention in the next article that they will focus more on the scope chain related to the domain execution context.