Let’s start with variable promotion

In the “VAR” era of ES5, there was a special phenomenon: no matter where we wrote our variable declarations in the program, they would end up at the top of the scope.


console.log(num)   //undefined

var num = 1

Copy the code

Magic variable lift

This code does not return an error, but instead prints a undefined. This is because the variable declaration is “promoted”, which is equivalent to this:


var num
console.log(num)  // undefined
num = 1

Copy the code

In the example above, we see that num as a global variable is promoted to the head of the global scope. A similar phenomenon occurs in a function scope:

function getNum() {
  console.log(num)  // undefined
  var num = 1  
}
Copy the code

Undefined is also printed here, because the variable declaration inside the function is raised to the top of the function scope. The above example is equivalent to:

function getNum() {
  var num 
  console.log(num)  // undefined
  num = 1  
}
Copy the code

The principle of variable promotion

In fact, JS also has a compilation phase, which differs from traditional languages in that JS does not finish the compilation work early, but executes it as it is compiled. Simply put, all JS snippets are compiled before they are executed, but the compilation process is very brief (perhaps a few subtlety or less) and then the code is executed.

Yes, JS, like any other language, goes through compilation and execution phases. It is during this brief compilation phase that the JS engine collects all variable declarations and validates them in advance. As for the rest of the statements, they will not take effect until the execution phase, when a specific sentence is executed. This is the mechanism behind variable promotion.

Disabled variables are promoted

console.log(num)  let num = 1 
Copy the code
VM324:1 Uncaught ReferenceError:  num is not defined     at <anonymous>:1:13
Copy the code

We can refer to var when we understand let. Let is very similar to var. The key difference between let and VAR is that when we declare variables with let, the variables are bound to the block scope, whereas var is not block scope-aware.

It’s worth noting that this rule is a little different when declaring reference types — the attribute values of reference types (including the elements of arrays) can be changed as long as you don’t change the reference reference.

const me = {
  name: 'Glennley'
}

me.name = 'zhangsan' / / no problem
Copy the code
const arr = [1.2.3.4]
arr.push(2)
 // arr [1, 2, 3, 4, 2]

arr.splice(0.1) 
// [2, 3, 4, 2]

const arrObj = {a:1.b:2}
arrObj.a = 2
arrObj.d = 'c:3'

// {a: 2, b: 2, d: "c:3"}
Copy the code

Temporary dead zone

Such codes are also often used as interview questions. The interviewer will ask you: What is the result of this code? In fact, this code will run nothing, it will report an error:

This is because ES6 explicitly states that if there are let and const commands in a block, the variables declared by the block to those commands form a closed scope from the start. If we try to use such variables before declaration, we get an error. This section of the danger zone has its own name, “temporary dead zone”. In the following demo, the me = ‘Glennley’ zone is a temporary dead zone.

{me = 'glennley' // let me; }Copy the code