What is variable promotion
In the process of JavaScript code execution, the JavaScript engine promotes the declaration part of variables and functions to the beginning of the code, which is called variable promotion
When a variable is promoted, it is given the default value undefined
The declaration part of a variable is improved:
console.log(a) // undefined
var a = 1
Copy the code
The declaration part of the function is improved:
console.log(add(1.2)) / / 3
function add(x, y) {
return x + y
}
Copy the code
Second, the principle of variable promotion
Variable promotion = physical movement?
No, the location of variable and function declarations in code does not change; they are put into memory by the JavaScript engine at compile time
A piece of code, when compiled, generates two parts:
- Execution context: The context in which JavaScript executes a piece of code
- The variable environment
- Lexical environment
- Executable code
Compile first, then execute:
- Compile phase: declarations of variables and functions are stored inThe variable environmentIn, the default value of the variable is set to
undefined
- Execution phase: The JavaScript engine looks for custom variables and functions from the variable environment
console.log(a)
console.log(add(1.2))
var a = 1
function add(x, y) {
return x + y
}
Copy the code
The compiled:
// The variable environment of the execution context
a = undefined
add = address1 -> function (x, y) { return x + y }
Copy the code
// Executable code
console.log(a) // undefined
console.log(add(1.2)) / / 3
a = 1
Copy the code
3. Defects of variable promotion
As a result, a lot of code is counterintuitive
1. Variables are easy to be overwritten without being noticed
function fn() {
var a = 1
if (true) {
var a = 2
console.log(a)
}
console.log(a)
}
fn()
Copy the code
The compiled:
// fn's execution context variable environment
a = undefined
Copy the code
// Fn's executable code
a = 1
if (true) {
a = 2
console.log(a) / / 2
}
console.log(a) / / 2
Copy the code
2. Variables that should have been destroyed were not destroyed
function fn() {
for (var i = 0; i < 5; i++) {
console.log(i)
}
console.log(i)
}
fn()
Copy the code
The compiled:
// fn's execution context variable environment
i = undefined
Copy the code
// Fn's executable code
for (i = 0; i < 5; i++) {
console.log(i) // 0 1 2 3 4
}
console.log(i) / / 5
Copy the code
Iv. How does ES6 solve the problems caused by variable promotion
Scope: The accessible scope of variables and functions
ES6 before:
- Global scope
- Function scope
After the ES6:
- Block-level scope
{}
ES6 implements block-level scope by using the let or const keyword
function fn() {
var a = 1
let b = 2
{
let b = 3
var c = 4
let d = 5
console.log(a)
console.log(b)
}
console.log(b)
console.log(c)
console.log(d)
}
fn()
Copy the code
Step 1: Compile and create the execution context
Inside the function:
- through
var
All declared variables are stored at compile time inThe variable environmentIn the - through
let
All declared variables are stored at compile time inLexical environmentIn the - Inside the scope block, through
let
Declared variableIt’s not stored in a lexical environmentIn the
// Fn's execution context
// Variable environment
a = undefined
c = undefined
// lexical context
b = undefined
Copy the code
Step 2: Continue executing the code
When entering a scoped block, variables declared by let are stored in a separate area of the lexical environment that does not affect variables outside the scoped block
Inside the lexical environment, a small stack structure is maintained:
- The bottom of the stack is the outermost variable of the function
- Entering a scoped block pushes variables inside that scoped block to the top of the stack
- When the scope execution is complete, the information for that scope is popped from the top of the stack
Implement ing…
// Fn's executable code
a = 1
b = 2
Copy the code
// Fn's execution context
// Variable environment
a = 1
c = undefined
// lexical context
b = 2
Copy the code
Implement ing…
// Fn's executable code
{
// Enter the scope block
}
Copy the code
// Fn's execution context
// Variable environment
a = 1
c = undefined
// lexical context
---
b = undefined
d = undefined
---
b = 2
Copy the code
Implement ing…
// Fn's executable code
{
b = 3
c = 4
d = 5
}
Copy the code
// Fn's execution context
// Variable environment
a = 1
c = 4
// lexical context
---
b = 3
d = 5
---
b = 2
Copy the code
Implement ing…
// Fn's executable code
{
// Search down the stack of the lexical environment. If it is found in a block in the lexical environment, it is returned directly to the JavaScript engine. If it is not found, it continues to look in the variable environment
console.log(a) / / 1
console.log(b) / / 3
}
console.log(b) / / 2
console.log(c) / / 4
console.log(d) // Uncaught ReferenceError: d is not defined
Copy the code
Five, the summary
- ES6 introduced block-level scoped keywords due to design flaws such as variable overwriting and variable contamination in JavaScript variable promotion
let
和const
To solve these problems - Variable promotion is implemented through the variable environment, and block-level scope is implemented through the stack structure of the lexical environment