Scope(Scope)
Ths scope is space police that rules the accessibility variables
Scope collects and maintains declared identifiers and sets access rules,
To put it simply, scope defines the accessibility of variables. JavaScript engine can search variables in scope according to identifiers, that is, to match identifiers with variables. Meanwhile, scope isolates variables so that variables in different scopes can have the same name but different values, without affecting each other
function foo() {
// "foo" function scope
let count = 0;
console.log(count); // logs 0
}
function bar() {
// "bar" function scope
let count = 1;
console.log(count); // logs 1
}
foo();
bar();
Copy the code
As shown in the code above, foo and bar belong to two different scopes and both define the same variable count, but hold different values without affecting each other
Scope nesting
function outerFunc() { // outer scope
let outerValue = 'I am outer scope'
function innerFunc() { // inner scope
console.log(outerValue) // log → 'I am outer scope'
}
innerFunc()
}
outerFunc()
Copy the code
OuterFunc and innerFunc form two scopes, inner scope is nested within outer scope, inner scope can access variables in outer scope, resulting in the following rules:
- Scopes can be nested
- An outer scope can access variables in an inner scope
Lexical scope
In the traditional process of compiling a language, the source code goes through three steps called compilation before execution,
Word Segmentation/Lexical Analysis (Tokenizing/Lexing)
In this process, strings of characters are broken down into meaningful code blocks called lexical units (tokens). Var a = 2; Is decomposed into: var, a, =, 2,; . Whether or not whitespace is considered a lexical unit depends on what whitespace means in a programming language
Parsing/Parsing
This process transforms the lexical unit stream (array) into a hierarchical nested Tree of elements that represents the Syntax structure of the program, called **” Abstract Syntax Tree “(AST)**.
Code generation
The process of turning an AST into executable code is called code generation. This process depends on the language, target platform, and so on.
The short answer is that there’s some way to set var a = 2; The AST transforms into a set of machine instructions that create a variable called A and store a finger in A
JavaScript you Don’t Know, Volume P5
There are two types of scopes:
- Lexical scope (or static scope)
- Dynamic scope
Lexical scope: its scope is determined at the lexical stage, not at the excution stage. Therefore, lexical scope has a lot to do with the writing position of the code, or it can be said that lexical scope is determined by the writing position of the code
Dynamic scope: Its scope is determined at code execution time
JavaScript engines use lexical scopes
How many scopes are there in JavaScript?
- Global scope
- Function scope
- Block scope: Note that block scope did not exist before ES6 (var does not have block-level scope when declaring variables), ES6 added it
let
,const
Such keywords form block-level scopes in the code blocks they declare
Scope chain
The Scope Chain is the hierarchy of scopes that will be searched in order to find a function or variable.
Because scopes can be nested, when the JavaScript engine does not find a variable to use in the current Scope, it will look up to the top Scope — Global Scope. If it does not find a variable in the Global Scope, The variable is then added to the Window object (in the browser environment, and not in strict mode), and this process, like a chain, is referred to as a scope chain
Note that this repeated lookup to the upper scope is actually implemented by outer in the Lexical Environment
Lexical Environment
Identifier is a data structure that holds identity-variable mapping. Identifier refers to variable names/function names, and variable refers to references to variables (including object and function) or values of primitive types
A Lexical Environment mainly consists of two parts:
- Environment Record: The place where variable and function declarations are stored
- declaration Environment Record
- Object Environment Record
- Global Environment Record
- Outer (Reference to the outer Environment) : Instantiated to the outer
Note: The Lexical Environment is created when the program executes
Something like the following structure:
lexicalEnvironment = {
environmentRecord: {
<identifier> : <value>,
<identifier> : <value>
}
outer: < Reference to the parent lexical environment>
}
Copy the code
Look at a practical example:
let language = 'JS';
function a() {
let b = 25;
console.log('Inside function a()');
}
a();
console.log('Inside global execution context');
Copy the code
The above code executes with two meanticists, one Global Lexical Environment and the other created by function A:
GlobalLexicalEnvironment = {
environmentRecord: {
language: 'JS'.a: <reference to function object>
},
outer: null
}
Copy the code
Note: Outer of Global Lexical Environment is null because its Lexical Environment is null for Global scope
Function A created the Lexical Environment:
FunctionLexicalEnvironment = {
environmentRecord: {
b: 25
},
outer: <GlobalLexicalEnvironment>
}
Copy the code
Function A’s outer points to the Global Lexical Environment because its code is contained within the Global scope
Execution Context
JavaScript creates an Execution Context when executing function or global code:
- Global code: Global Execution Context
- Function: Function Execution Context
When creating the Execution Context, the Lexical Environment is created accordingly.
As for the relationship between Lexical Scope, Execution Context and Lexical Environment, MY understanding is as follows: The creation of the latter two will actually depend on the lexical scope, as it determines the accessibility of the identifiers, which in turn is related to the creation of the lexical Environment (related to outer).
About how the JavaScript engine handles execution context:
- When the JavaScript engine executes code in the global scope, creates a Global Execution Context and adds itExecution Context Stack(also called: Call Stack), and set it toRunning Lexical Environment
- When Global Execution Context is created, the Global Lexical Environment is also created, and the Lexical Environment does two main things: Implement Environment Record(binding of identifiers to variables) and outer pointing (pointing to the outer lexical Environment, in the Global Execution Context, outer pointing to NULL)
- When the function is executed, creates a Function Execution Context for the current Function and adds it to the Execution Context Stack, setting it to running Execution Context
- Creating a Function Execution Context does the same thing as creating a Global Execution Context, except that outer points to the Global Execution Context (PS: Nested calls to functions are also nested in lexical scopes.
- When the Function Execution is complete, the Function Execution Context of the current Function is removed from the Execution Context Stack and destroyed. Also set the Global Lexical Environment to the Running Lexical Environment
Note: The above procedure only considers the absence of nested functions, which are similar
Pay attention to
-
There are many differences between the Specification of ES5 and the Specification of ES6, and no distinction has been made above
-
Some of the things described above are omitted, for example:
-
Execution Context consists of not only Lexical Environment, but also Variable Environment and PrivateEnvironment.
-
The type of Environment Record can be: Declaration Environment Record, Object Environment Record and Global Environment Record The standard explicitly states that the Environment Record has [outer], which is used to refer to the outer Environment Record, whereas in our description above, the [outer] field is in the Lexical Environment, It has the same relationship with Environment Record, including most articles on the Internet, which are described in this way, but it seems to be inconsistent with the standard, I wonder whether there is a misunderstanding of the standard? A: This is mainly because ECMA-262 5.1 Edition and ECMA-262 12th Edition are different. 5.1 is released in 2011, and 12th Edition is the latest Edition in 2021. For the description of Lexical Environment in 5.1, no detailed description of Lexical Environment is found in 12th, but only the description of Environment Record
-
confusion
- Lexical Scope is determined at the Lexical analysis stage, while Execution Context and Lexical Environment are created at the Execution stage. Is the creation of the Execution Context and Lexical Environment dependent on the Lexical Scope? From what we’ve learned so far, it looks like it is
- The terms Scope and Lexical Scope and their implementations are not mentioned in the specification of ECMAScript262. Is it because Scope generation is an essential routine operation during code compilation and execution that it is not mentioned in the specification? According to the concept of scope, Lexical Environment is most relevant to it in the specification. Is it the concrete realization of scope?
Reference:
-
Understanding Scope and Scope Chain in JavaScript
-
Scope Chain & Lexical Environment in Javascript
-
Execution Context in Javascript
-
Executable Code and Execution Contexts
-
Ecma262 5.1 th