The principle of the scope chain in JavaScript

Source: Internet
Author: User

Execution Environment

 The formation of the scope chain is related to the execution environment (execution environment), where the execution environment is generated in JavaScript in the following 3 scenarios:

1 Entering the Global environment

2 Calling the Eval function

3 Calling function

You can create an execution environment B on an execution Environment B, and you can also create an execution Environment C ..., this series of execution environment constitutes the execution environment stack, the newly created execution environment is located at the top of the stack (the bottom of the stack is always the global execution environment), after the end of the execution environment (the associated Code execution end) Will be ejected from the station, the execution environment underneath will become the new stack top. As shown in the following:

An execution environment consists of 3 parts: lexicalenvironment,variableenvironment,thisbinding. The thisbinding is the this value, and lexicalenvironment and variableenvironent are equivalent to two pointers, which point to lexical environment ( Note that not lexicalenvironment), Lexical environment contains the identifier.

Lexical environment is also composed of 2 parts: the environment record and a outer pointer, where the outer pointer points to the Lexical environment of the execution environment under the current execution environment, and environment The record is the various identifiers in the bound program.

Environment record can be subdivided into 2 types: one called Declaration environment record, the other is an object environment record. Both types of environment records record the identifiers used in the program, except that the Declaration environment record is primarily bound by the declaration of the variable and the declaration of the function, while object environment The record is associated with a object,object environment record that is bound to a property associated with the variable (such as with syntax). This allows you to access the properties of the variable in JavaScript code without displaying the object specified.

The entire relationship is as follows:

Note that the outer pointer to the global execution environment at the bottom of the execution environment stack points to null. When looking for an identifier, start looking for the lexical environment of the topmost execution environment, and if not, go to the next lexical environment that the outer pointer points to (the illustration above is for demonstration, In practice, the lexical environment that the outer pointer points to is probably not the lexical environment of the adjacent execution environment, until the variable is found or the outer pointer points to NULL, so the outer pointer is connected by the lexical Environment is the scope chain at which the current function runs.

In the execution environment just established, lexicalenvironment and Variableenvironment point to the same lexical environment, but if in this execution environment encountered a special syntax, such as with, Then the lexicalenvironment will point to the new lexical Record, and when with runs the lexicalenvironment will point to the lexical that variableenvironment refers to Environment, as shown in the following code:

function f () {    var i = 1;      with (document) {        write ("Hello");    }     var j = 2;}

The execution environment before executing the WITH statement is as follows:

The execution environment is as shown when executing the WITH statement (note that no new execution environment is created, only one lexical environment is added):

Execute the WITH statement after the execution environment as shown:

Composition of the environment record

Whether the environment record is a declaration environment record or an object environment record, it is bound to the information of the identifier in the current execution environment, that is, Key-value, Key is the identifier name, and value is the corresponding values, as shown in:

Enter function to form execution environment

Suppose you have the following code:

functionF (A, B, c) {vari = 1; varj = 2; //Functions Declaration (function Declaration)    functionInner (k, L, m) {vari = 1; varp = 2; varQ = 3; }    //functions Expressions (function expression)    varFVar =function(x, Y, z) {vari = 1; varR = 2; vars = 3; }}

When this function is called with F (1, 2, 3) in JavaScript, a new execution environment is created for the function, and the identifier information inside the function is first placed in the environment record before any code inside the function is executed. The binding identifier in the environment record can be divided into 4 parts (the order of the 4 sections is fixed in the environment record, and the order of each part is based on the sequence of identifiers): function arguments, function declarations, arguments, Variable declaration, after binding, the execution environment of function f is as follows:

The parameter identifier is directly bound to the argument value passed to the function;

The function declaration identifier binds the function object (which is also the function declaration identifier that can be used first, and then declares the reason because the function declaration identifier was added to the environment record before the code was run, and the function object was bound);

The arguments binds to the arguments object;

Variable declarations (including function expressions, which can also be thought of as variable declarations), are bound to undefined, and only when the code actually runs into a statement assigned to a variable will the variable hold the value that we assign to the variable (which can be used before the variable declaration, But the value of the variable is always the reason for undefined).

The variables I and J in the environment record are the variables inside the function f, independent of the function declaration inner and the variables inside the function expression Fvar, because they are defined only and not yet called.

It is important to note that:

1) The environment record binds the arguments identifier to the condition that the parameter names and function declaration identifiers are not named arguments;

2) If more than one function uses the same identifier, the environment record will have only one record, and the record binds to the last declared function object, that is, the function object that was declared before the function object is overwritten, and if the function declaration identity matches the name of the parameter identifier, Then the function identifier overrides the parameter identifier, that is, if you have the following code:

function F (A, B, c) {    alert (a);     function A () {       ...    }    alert (a);}

When called with F (1, 2, 3), both alert displays function A, not parameter a.

3) If the variable declaration identifier is the same as the previous argument, the function declaration, and the arguments identifier, then the variable identifier is not bound, that is, if the following code:

function F (A, B, c) {    function  I () {      ...    }    alert (i);     var i = 1;    alert (i);}

When called with F (1, 2, 3), the first alert shows function I instead of the undefined value, because the variable declaration i has the same name as the function I, is not bound, and the second alert shows 1 because it runs var i = 1; after that, environment The value corresponding to the identifier I in the record is given 1.

Also, if you declare the same variable more than once, there will only be one record in the environment record.

The remaining question is how the new execution environment is associated with the outer execution environment when the function is called, that is, how the outer pointer of the new execution environment knows which execution environment to point to. The answer is that when you define a function, the internal property [[scope]] of the function object references the lexical environment that defines itself, and when the call occurs, the outer pointer points to the lexical environment referenced by [[scope]]. Suppose you have the following code:

function F1 () {    var f = F2 ();     f ();  } function F2 () {    var i = 1;     return function () {            = 2;    }}

When F2 is called, the execution environment is as follows:

When the call F2 ends, the execution environment is as follows:

The F2 call ends, and the F2-related execution environment pops up from the top of the stack, while the lexical environment F2 execution Environment reference is referenced by the [[scope]] property of the function object F and therefore will not be garbage collected with the top of the F2 execution environment pop-up stack.

When the function f is called, the execution environment is as follows:

As can be seen from the top f lexical environment, along the outer pointer, the function f can access the function F2 inside the local variable i, which is the principle of closure.

Resources

ECMA-262

The principle of the scope chain in JavaScript

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.