You do not know the execution context of JavaScript -- Item19 (execution context)

Source: Internet
Author: User

You do not know the execution context of JavaScript -- Item19 (execution context)

In this article, I will go into the execution context, the most basic part of JavaScript ). After reading this article, you should understand what the interpreter has done, why functions and variables can be used before declaration, and how their values are determined.

1. EC-execution environment or execution Context

Whenever the Controller reaches the ECMAScript executable code, the Controller enters an execution context (high concept ).

In javascript, EC is divided into three types:

Global Code-this is the default code running environment. Once the code is loaded, the engine first enters this environment. Function-level code-when a function is executed, the code in the function body is run. Eval code-the code that runs in the Eval function.

The establishment of EC is divided into two phases:Enter execution context (creation stage)AndExecution phase (activation/code execution).

Entering the context stage: Occurs when a function is called, but before the specific code is executed (for example, before the function parameter is embodied)
Create a Scope Chain to create variables, functions, and parameters. Evaluate the value of "this. Code execution stage:
Variable assignment function reference to explain/execute other code.

We can regard EC as an object.

EC = {VO: {/* The arguments object in the function, parameters, internal variables, and function declaration */}, this :{}, Scope: {/* VO and VO In all parent execution contexts */}}

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?

2. ECS-execution context Stack

The execution context of a series of activities logically forms a stack. The bottom of the stack is always the global context, and the top of the stack is the current (active) Execution context. When switching between different execution contexts (exiting and entering the new execution context), the stack will be modified (in the form of stack pressure or rollback ).

Stack pressure: Global EC-> Local EC1-> Local EC2-> current EC
Outbound Stack: Global EC <-local EC1 <-local EC2 <-current EC

We can use arrays to represent the environment Stack:

ECS = [local EC, global EC];

Each time the Controller enters a function (even if the function is called recursively or used as the constructor), the stack is pressed. The process is similar to the push and pop operations of javascript arrays.

The JavaScript interpreter in the 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:

(function foo(i) {    if (i === 3) {        return;    }    else {        foo(++i);    }}(0));

This Code calls itself three times and adds one to the value of I 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, about the 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. 3. VO-variable object

Each EC corresponds to a variable object VO, and all the variables and functions defined in this EC are stored in the corresponding VO.

VO is divided into Global context VO (global object, Global object, which we usually call global object) and function context AO.

VO: {// data in the context (function arguments), function declaration (FD), and variable Declaration (var ))}

1. When entering the execution context, the VO initialization process is as follows:

Function parameters (when entering the context of function execution) -- an attribute of the variable object. Its attribute name is the name of the parameter, and its value is the value of the real parameter. For parameters that are not passed, its value is undefined;

Function declaration (FD) -- an attribute of a variable object. Its Attribute names and values are all created by the function object. If the variable object already contains attributes with the same name, replace its value;

Variable Declaration (var, VariableDeclaration) -- an attribute of the variable object. Its attribute name is the variable name and its value is undefined; if the variable name is the same as the declared function name or function parameter name, the existing attributes are not affected.
Note: The process is sequential.

2. Some undefined values in VO will be determined during code execution.

4. AO activity objects

In the context of function execution, VO cannot be accessed directly. It mainly acts as an active object (AO.
How can this sentence be understood? When the EC environment is a function, we access AO rather than VO.

VO(functionContext) === AO;

AO is created when you enter the execution context of the function and initialize an arguments attribute for the object. The value of this attribute is an Arguments object.

AO = {arguments: {callee:, length:, properties-indexes: // The parameter value passed by the function }};

The FD format can only be as follows:

function f(){}

When a 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.

The internal execution order is as follows:

1. Search for the code that calls the function.

2. Create an execution context before executing the function code.
3. Enter the creation stage:

Initialize the scope chain: Create a 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 (specifically the name of the function) on the variable object for each detected function, and a reference pointing to the function in memory. If the function name already exists, the reference pointer will be overwritten. The declaration of variables in the context of the scan: This is the declaration of each detected variable. Create an attribute on the variable object, that is, the name of the variable, and initialize the value of the variable to undefined, if the variable name already exists in the variable object, no operations will be performed and scanning will continue. Obtain the value of "this" in the context.

4. Activation/code execution phase:
Run/interpret the function code in the current context, and execute the variable value with a line of code.

Example

1. Specific instance

function foo(i) {    var a = ‘hello‘;    var b = function privateB() {    };    function c() {    }}foo(22);

When foo (22) is called, The creation status is as follows:

fooExecutionContext = {    scopeChain: { ... },    variableObject: {        arguments: {            0: 22,            length: 1        },        i: 22,        c: pointer to function c()        a: undefined,        b: undefined    },    this: { ... }}

As you can see, the creation status is responsible for processing the name of the defined attribute, not assigning specific values to them, as well as processing the form and real parameters. Once the creation stage is complete, the execution flow enters the function and the activation/code execution stage. After the function execution is complete, you can see the following:

fooExecutionContext = {    scopeChain: { ... },    variableObject: {        arguments: {            0: 22,            length: 1        },        i: 22,        c: pointer to function c()        a: ‘hello‘,        b: pointer to function privateB()    },    this: { ... }}

2. VO example:

alert(x); // functionvar x = 10;alert(x); // 10x = 20;function x() {};alert(x); // 20

When entering the execution context,

ECObject={  VO:{    x:
  
     }};
  

When executing the Code:

ECObject = {VO: {x: 20 // with the same name as Function x. Replace it with 10 and then 20 }};

For the above process, we will explain in detail.

When entering the context, VO will be filled with function declaration; at the same stage, there will be variable Declaration "x", but, as mentioned earlier, the variable declaration is after the function declaration and function parameters, and the variable declaration does not conflict with the existing function declaration with the same name and function parameters. Therefore, at the context stage, the VO filling format is as follows:

VO = {}; VO ['X'] = <reference to the function declaration 'X'> // find var x = 10; // if the function "x" is not defined yet // then x is undefined. However, in our example, the // variable declaration does not affect the function value VO ['X'] = <the value is not affected, but is still a function>

During code execution, VO is modified as follows:

VO['x'] = 10;VO['x'] = 20;

The following example shows that the variables are stored in VO at the context stage. (therefore, although the else code block is never executed, "B" is still in VO)

if (true) {   var a = 1;} else {   var b = 2;}alert(a); // 1alert(b); // undefined, but not b is not defined

3. AO example:

function test(a, b) {   var c = 10;   function d() {}   var e = function _e() {};   (function x() {});}test(10); // call

WhenExecution ContextIts AO is:

testEC={    AO:{            arguments:{            callee:test            length:1,            0:10       },        a:10,        c:undefined,        d:
  
   ,        e:undefined    }};
  

It can be seen that in the establishment phase, VO has not only arguments, function declaration, but also specific attribute values assigned to parameters. Other variable attributes are undefined by default. Function expressions do not affect VO. Therefore, (function x () {}) does not exist in VO.

WhenRunWhen test (10), its AO is:

testEC={    AO:{        arguments:{            callee:test,            length:1,            0:10        },        a:10,        c:10,        d:
  
   ,        e:
   
        }};
   
  

It can be seen that the variable attribute is assigned a specific value only at this stage.

5. Hoisting decryption

In the previous JavaScript Item, the variable and function declaration were promoted 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 active activity objects, which makes it easy to understand why. See the following example:

(Function () {console. log (typeof foo); // function pointer console. log (typeof bar); // undefined var foo = 'hello', bar = function () {return 'World' ;}; function foo () {return 'hello ';}}());

We can answer the following questions:

1. 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.

2. 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.

3. 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.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.