Es6 has added new declarations such as let and const. They are block-level scopes. Const can only be declared as constants, etc.. Not really. I happened to be talking to a friend about it recently. Such a new understanding to sort out!
JS execution process and variable promotion
-
Syntax analysis stage: the loaded code is checked syntactically, and the pre-compilation stage is entered after the check is completed.
-
Precompile phase: Collect function names and variable promotions, and determine the this reference and scope chain
-
Execution phase: Execution through an event loop
As a result of precompilation, all variable declarations will be promoted to the header of the code, in what is called variable promotion.
Console. log(a) var a = "upgrade ";Copy the code
Output “variable boost”
var a; console.log(a); A = "variable promotion"Copy the code
Output “undefined”
-
JavaScript only improves declarations, not their initialization. If a variable is used before it is declared and assigned, the value is undefined.
-
Functions are given priority over variables. This means that the function will be pushed up to the front
Scope of a variable
MDN interpretation: The current execution context. The context in which values (en-US) and expressions are “visible” or accessible. Let’s look at an example
var x = "Scope";
console.log(x); //Scope
}
console.log(x); // error
Copy the code
The Scope of variable X is the Scope function. The Scope refers to the area of the accessibility or visibility of the variable. Which part can access the variable or where can the variable be seen
function a(){
var x = 1;
},
funcction b(){
var x = 3;
}
Copy the code
// This is ok
Because of the scope, the same variable name does not conflict
Global and local scopes and block-level scopes
Objects that can be accessed anywhere in the code have global scope
Local scopes are accessible only in fixed snippets of code, most commonly inside functions
Block-level scopes can be declared via lets, const, whose scope is the nearest {}, and cannot be accessed from outside the brace
Inner scopes can access outer scopes, but not vice versa. This means that global variables can be read inside a function, but variables inside a function cannot be read outside the function.
{ let a = 'Hello World! '; var b = 'English'; console.log(a); // Prints 'Hello World! } // Output 'English' console.log(b); R: greeting is not defined console.log(a);Copy the code
Var can be accessed outside of {}, not block-level scope
Because of business requirements, many times you need to read local variables inside a function, which can be done with closures.
The scope chain
When a variable is used in JavaScript, the JavaScript engine looks up the value of the variable in scope. If it cannot find the variable, it looks in the external scope and continues to do so until it finds the variable or reaches the global scope.
If it still can't find the variable, it either implicitly declares it globally (if not in strict mode) or returns an error.
let a = 'hello';
function chain() {
let b = 'world';
// 输出 'world'
console.log(b);
// 输出 'hello'
console.log(a);
num = 10;
console.log(num); // 输出10
}
chain();
Copy the code
When the chain method is executed, the JS engine looks for the b variable, finds it in the current scope, and then looks for the A variable, which is not in the current scope. The js engine looks for it in the outer scope. We assign num, and the JS engine looks for the variable in the current scope, and then in the outer scope.
Lexical environmentLexical Environment
To understand how JavaScript engines perform variable lookups, we must understand the concept of lexical environments in JavaScript.
In JavaScript, for every function run, the code block {… }, as well as the whole script, has an internal (hidden) correlation object called the Lexical Environment.
The lexical environment object consists of two parts:
-
Environment Record – an object that stores all local variables as its properties (including some other information, such as the value of this).
-
A reference to an external lexical environment, associated with external code.
A “variable” is justEnvironmental recordsA property of this particular internal object. “Get or modify a variable” means “get or modify a property of the lexical environment.”This is what is called associated with the entire scriptglobalLexical environment.
In the image above, the rectangle represents the environment record (variable store) and the arrow represents the external reference. The global lexical environment has no external references, so the arrow points to NULL.
As the code starts and continues to run, the lexical environment changesThe rectangle on the right illustrates how the global lexical environment changes during execution:
-
When the script starts running, the lexical environment is prepopulated with all declared variables.
- Initially, they are in the “Uninitialized” state. This is a special internal state, which means the engine knows about the variable but is using it
let
It cannot be referenced before it is declared. It’s almost as if the variable doesn’t exist.
- Initially, they are in the “Uninitialized” state. This is a special internal state, which means the engine knows about the variable but is using it
-
Then the let phrase definition appears. It has not been assigned, so its value is undefined. From this point on, we can use variables.
-
Phrase is given a value.
-
The value of phrase has been modified.
It all seems pretty simple now, doesn’t it?
-
Variables are attributes of special internal objects that are related to the block/function/script that is currently being executed.
-
Manipulating variables is actually manipulating properties of the object.
The lexical environment is a specification object
A “lexical environment” is a specification object: it is simply an object that exists “theoretically” in a programming language specification to describe how things work. We can’t get this object in code and manipulate it directly.
The JavaScript engine can also optimize it, such as clearing unused variables to save memory and performing other internal tricks, but the explicit behavior should be the same.
My summary: The lexical environment is where variable and object references are stored during JS execution.
How the LEXICAL environment is used by the JS engine to determine scope and scope chains.
When a function runs, at the beginning of the call, a new lexical environment is automatically created to store the local variables and arguments of the call.
For example, forsay("John")
, it looks like this (the current execution position is on the line marked by the arrow) :
During this function call, we have two lexical environments: internal (for function calls) and external (global) :
-
The internal lexical environment corresponds to the current execution of SAY. It has a single attribute: name, the parameter to the function. We are calling say(“John”), so the value of name is “John”.
-
The external lexical environment is the global lexical environment. It has the phrase variable and the function itself.
The inner lexical environment references OUTER.
In this example, the search is as follows:
-
For the name variable, when an alert in SAY attempts to access name, it is immediately found in the internal lexical environment.
-
When it tries to access phrase, however, there is no phrase inside, so it follows the reference to the external lexical environment to find it.
So, when code wants to access a variable — it searches the internal lexical environment first, then the external environment, then the more external environment, and so on, all the way to the global lexical environment.
Focus on
A scope is a region where variables are visible and accessible. Just like functions, scopes in JS can be nested, and the JS engine will traverse the scope chain to find the variables used in the program.
JS uses a lexical environment, which means that the scope of variables is determined at compile time. The JS engine uses a lexical environment to store variables during program execution.
let&const
Temporal Dead Zone (TDZ)
var b
function tdz() {
b = 'world';
let b
console.log(b)
}
tdz(); //print error
Copy the code
The variable is not available within the code block until it is declared using the let command. This is grammatically called a “temporary dead zone.”
ES6 makes it clear that temporary dead zones and let and const statements do not promote variables. The main purpose of ES6 is to reduce runtime errors and prevent the variable from being used before it is declared, resulting in unexpected behavior. Such errors are common in ES5, and with this provision, it’s easy to avoid them.
In short, the essence of a temporary dead zone is that the variable you want to use already exists as soon as you enter the current scope, but you can’t get it until the line of code that declared the variable appears.
const&let
-
Const, like let, has a temporary dead zone
-
Both are block-level scopes
-
There is no variable promotion
-
The difference is that const must be assigned at the time it is declared and not at a later time.
const a;
// SyntaxError: Missing initializer in const declaration
Copy the code
A very common question is, does changing the value of an attribute in an object that is const get an error?
The first thing most people would say is, because const can only be declared as constants, and constants are immutable, so it gets an error
Const actually guarantees that the pointer to the memory address to which the variable points is fixed. No error is reported as long as the pointer is unchanged.
The resources
Developer.mozilla.org/zh-CN/docs/…
Useful. Javascript. The info/closure# ci -…