preface
This article contains 2922 words and takes about 8 minutes to read.
Blanket: what is the meaning of the variables increase, the use of var, let, const, function and variable functions declared in the class in the variable lift what is the difference between of the time.
- Reapply in Modern JavaScript — let, const, and var
- Public account: “front-end advanced learning”, reply to “666”, get a package of front-end technology books
Be vulgar or be lonely.
The body of the
Variable promotion in Javascript means that it can be used in an application before a variable is declared:
console.log(a); // undefined
var a = 1;
Copy the code
As you can see, we can call a normally before the variable a is declared, and the actual code looks more like this:
var a;
console.log(a); // undefined
a = 1;
Copy the code
In fact, the code is not changed, the above code is just a guess, and the Javascript engine does not move or change the result of the code as it executes these lines. So what happened?
Variable ascension
At compile time, the moment the code is actually executed, the engine logs all variable and function declarations in the code block. These function and variable declarations are recorded in a data structure called the lexical environment. A lexical environment is a data structure in the Javascript engine that records variable and function declarations and is stored directly in memory. So console.log(a) above works fine.
What is lexical context
A lexical environment is a structure of identity-variable mappings (identifiers are the names of variables/functions, and variables are references to actual objects [objects containing functions and array types] or underlying data types).
Simply put, the lexical environment is where the Javascript engine stores references to variables and objects.
The structure of the lexical environment is represented in pseudocode as follows:
LexicalEnvironment = {
Identifier: <value>,
Identifier: <function object>
}
Copy the code
To learn more about lexical environments, see our previous translation: Understanding the execution context and execution stack in Javascript.
Understand the lexical environment let me use the var, in turn, a look, const, let, function, class declaration of variables or functions.
Function declaration enhancement
helloWorld(); // Prints 'Hello World! '
function helloWorld(){
console.log('Hello World! ');
}
Copy the code
We already know that function declarations are recorded in the lexical environment and stored in memory at compile time, so we can access the function before it is actually declared.
The above function declaration is stored in a lexical environment like this:
lexicalEnvironment = {
helloWorld: < func >
}
Copy the code
So during code execution, when the Javascript engine encounters helloWorld(), it looks in the lexical environment, finds this function, and executes it.
#### function expression
Note that only function declarations are promoted directly. Functions declared using function expressions are not promoted.
helloWorld(); // TypeError: helloWorld is not a function
var helloWorld = function(){
console.log('Hello World! ');
}
Copy the code
As above, the code reported an error. The helloWorld declared with var is a variable, not a function, and the Javascript engine treats it as a normal variable rather than assigning it a value in the lexical context.
Save it in a lexical environment like this:
lexicalEnvironment = {
helloWorld: undefined
}
Copy the code
The above code can be rewritten to work as follows:
var helloWorld = function(){
console.log('Hello World! ');
}
helloWorld(); // Prints 'Hello World! '
Copy the code
Var variable promotion
Let’s look at an example of using var to declare a variable:
console.log(a); / / print 'undefined'
var a = 3;
Copy the code
Function should print 3, but undefined is actually printed.
** Remember: ** The so-called declaration promotion is only at compile time when the Javascript engine stores function and variable declarations in the lexical environment, but does not assign values to them. The lexical environment is updated during the execution phase, when the assignment line is actually executed.
But why does the code above print undefined?
The Javascript engine stores the variable declared using VAR in the lexical environment at compile time and initializes it as undefined. At the execution stage, the values of variables in the lexical environment are updated when the assignment line is executed.
So the lexical environment for the above code is initialized like this:
lexicalEnvironment = {
a: undefined
}
Copy the code
This also explains why the previous function declaration with function expressions reported an error and why the code above prints undefined. When the code executes to var a = 3; This line of code will update the value of a in the lexical environment. The lexical environment will update as follows:
lexicalEnvironment = {
a: 3
}
Copy the code
Let and const variables are promoted
Look at an example of declaring a variable using let:
console.log(a);
let a = 3;
Copy the code
Output:
Uncaught ReferenceError: Cannot access 'a' before initialization
Copy the code
Let’s look at another example of declaring a variable using const:
console.log(b);
const b = 1;
Copy the code
Output:
Uncaught ReferenceError: Cannot access 'b' before initialization
Copy the code
Unlike var, let or const code of the same structure will return an error.
Don’t variables declared with let and const get promoted?
In fact, all variables declared in the Javascript (var, const, let, function, class) are variables of ascension. Variables declared with var are initialized to undefined in lexical contexts, but variables declared with let and const are not.
Variables declared with let and const are not assigned until the line to which they are assigned is executed. This means that an error will be reported if a variable is accessed until the line to which the variable is declared is executed. This is known as a temporary dead zone (TDZ). That is, a variable cannot be accessed until it has been declared.
When the line of the variable declaration is executed, but there is still no assignment, the variable declared using let is initialized to undefined; An error is reported for variables declared using const; Look at a practical example:
let a;
console.log(a); / / output is undefined
a = 5;
Copy the code
During code compilation, the Javascript engine stores the variable A in the lexical environment and leaves it uninitialized. The lexical environment looks like this:
lexicalEnvironment = {
a: <uninitialized>
}
Copy the code
If you try to access variables a or B at this point, the Javascript engine will find the variable in the lexical environment, but it is uninitialized and will throw a reference error.
Then, in the execution phase, the Javascript engine evaluates the assigned value when it comes to the line of assignment (lexical binding). If no value is assigned, just a simple declaration, the variable declared by the let will be assigned as undefined. The lexical environment looks like this:
lexicalEnvironment = {
a: undefined
}
Copy the code
When the line a = 5 is executed, the lexical environment is updated again:
lexicalEnvironment = {
a: 5
}
Copy the code
Now consider declaring code with const:
let a;
console.log(a);
a = 5;
const b;
console.log(b);
Copy the code
Output:
Uncaught SyntaxError: Missing initializer in const declaration
Copy the code
Console.log (a) (a); console.log(a) (a); This line of code.
** Note: ** in a function, no error is reported as long as the variable can be referenced after the declaration.
What does that mean? Look at the following code:
function foo () {
console.log(a);
}
let a = 20;
foo(); / / print 20
Copy the code
But the following code will report an error:
function foo () {
console.log(a);
}
foo();
let a = 20; // Error: Cannot access 'a' before initialization
Copy the code
Here the cause of the error combining in Javascript execution context and the execution stack is needed to understand, because the global execution context lexical environment preservation of uninitialized variable a, call the function foo, created a function execution context, then the function foo execution to access global execution context variable a, But a is still in the uninitialized state (let a = 20 has not yet been executed). Therefore, an error was reported.
Let and const declare variables that have only temporary dead zones and do not promote variables.
let a = 1;
{
console.log(a);
let a = 2;
}
Copy the code
The above code will get an error:
Uncaught ReferenceError: Cannot access 'a' before initialization
Copy the code
If there is no variable promotion, theoretically no error should be reported.
Class declaration promotion
Similar to let and const, classes that use a class declaration are promoted. The class declaration is then kept in the lexical environment but uninitialized until the line of code that assigns a value to a variable is initialized. In addition, classes declared by class also have temporary dead zones (TDZ). See the examples:
let peter = new Person('Peter'.25);
console.log(peter);
class Person {
constructor(name, age) {
this.name = name;
this.age = age; }}Copy the code
Print:
Uncaught ReferenceError: Cannot access 'Person' before initialization
Copy the code
Rewrite the following to work properly:
class Person {
constructor(name, age) {
this.name = name;
this.age = age; }}let peter = new Person('Peter'.25);
console.log(peter);
// Person { name: 'Peter', age: 25 }
Copy the code
At compile time, the lexical environment looks like this:
lexicalEnvironment = {
Person: <uninitialized>
}
Copy the code
Then execute to the line of code in the class declaration, where the lexical environment looks like this:
lexicalEnvironment = {
Person: <Person object>
}
Copy the code
** Note: instantiating an object using a constructor does not raise an error:
let peter = new Person('Peter'.25);
console.log(peter);
function Person(name, age) {
this.name = name;
this.age = age;
}
// Person { name: 'Peter', age: 25 }
Copy the code
The above code works fine.
Such expressions
Like function expressions, class expressions are promoted, for example:
let peter = new Person('Peter'.25);
console.log(peter);
let Person = class {
constructor(name, age) {
this.name = name;
this.age = age; }}Copy the code
Error:
Uncaught ReferenceError: Cannot access 'Person' before initialization
Copy the code
To work properly, rewrite the following:
let Person = class {
constructor(name, age) {
this.name = name;
this.age = age; }}let peter = new Person('Peter'.25);
console.log(peter);
// Person { name: 'Peter', age: 25 }
Copy the code
This means that function expressions and class expressions follow the same rules as variable declarations.
conclusion
Whether the var, const, let, function, class declaration of variables or functions are promoted. Understanding variable promotion helps us write better code. The overall situation of variable promotion is summarized as follows:
var
: there is variable promotion, which is initialized at compile timeundefined
;let
: there is variable promotion, there is temporary dead zone (TDZ), execution phase, if no value is assigned, then initialized toundefined
;const
: there is variable promotion, there is a temporary dead zone (TDZ), if there is no assignment, an error will be reported at compile time;function
: there is variable promotion, which can be accessed and performed before variable declaration;class
: There is variable promotion and temporary dead zone (TDZ);
The ability is limited, the level is general, welcome to erratum, greatly appreciated.
To subscribe for more articles, follow the public account “Front-end Advanced Learning” and reply to “666” for a package of front-end technology books