In interviews, we are often asked the difference between let, const and var, and my answers are invariably the same:

  • Variable ascension

    Var boosts variables, let and const do not

  • Temporary dead zone

    Because var does variable promotion, it can be accessed before declaration without creating a temporary dead zone.

    Let and const are not promoted and cannot be used until they are declared, creating a temporary dead zone

  • Repeat statement

    Var can be repeated, but let and const cannot

  • Block scope

    Var does not form block scope. Let and const do

  • To assign a value

    Variables declared by var and let can be reassigned, but const cannot.

    If a const declares a variable containing a reference address, it can change the value of the reference object, but it cannot be assigned another value

The same answer every time, and the interviewer didn’t say anything.

However, once in an interview, the interviewer asked me how to explain the so-called temporary dead zone of LET. Are let and const variable promoted at all? I didn’t answer, then the interviewer and I explained, and recommended me to see a great spirit of the article: zhuanlan.zhihu.com/p/28140450

The conclusion from this article and the articles mentioned in this article is as follows:

The “creation” process of the LET has been improved, but initialization has not.

Why? Start with the life cycle of a variable!

1. The life cycle of variables

I prefer this article here: JavaScript Variables Lifecycle: Why Let Is Not Hoisted

First let’s learn about the life cycle of a variable:

When engines use variables, their life cycle consists of the following phases:

  1. Declaration stage (Declaration phase) is registering variables in scope.
  2. Initialization phase (Initialization phaseIs to allocate memory and create bindings for variables in scope. In this step, the variable will be used to automatically initialize undefined.
  3. Distribution phase (Assignment phaseAssigns a value to an initialization variable.

A variable is in a unified state when it passes through the declaration phase, but has not yet reached the initialization state.

Note, however, that the declaration phase is a different term from variable declaration in general in terms of the variable life cycle. In short, the engine handles variable declarations in three phases: the declaration phase, the initialization phase, and the assignment phase.

1.1 Life cycle of var variables

Variables declared by var are declared and initialized at the beginning of their scope. There is no gap between the declaration and initialization phases.

function var_variable(){
  console.log('Before the declaration stage',one_variable);
  var one_variable;
  console.log('Before assignment',one_variable);
  one_variable = 'be assigned';
  console.log('After assignment', one_variable);
}
//console.log('Is the variable declared by var accessible outside the function scope?', one_variable); //one_variable is not defined var_variable();Copy the code

Running results:

Undefined before undeclared phase undefined before assignment undefined after assignment be assignedCopy the code

Variables pass through the declaration phase and immediately initialize the phase at the beginning of the scope before any statement is executed (step 1 above). The position of the var variable statement in the function scope does not affect the declaration and initialization phases.

After declaration and initialization, but before the assignment phase, the variable has undefined value and can be used.

In the assignment phase variable = ‘value’, the variable will receive its initial value (step 2 above).

1.2 Function declaration lifecycle

Function funName() {function funName() {… }

The function declaration is “created, initialized, and assigned” before the code executes.

function sumArray(array) {
  return array.reduce(sum);
  function sum(a, b) {
    returna + b; } } sumArray([5, 10, 8]); / / = > 23Copy the code

When you execute JavaScript sumArray([5, 10, 8]), it will enter the sumArray function scope. Within this range, sum passes through all three phases: declaration, initialization, and assignment, immediately before any statement is executed. Function sum(a, b) {function sum(a, b) {… }.

1.3 Let variable life cycle

The let variable is handled differently than var. The main difference is that the declaration and initialization phases are separate.

leta = 1; {// Can not access "a" before initialization, where a refers to the following A, not the global A, at this time a has not been initialized, // so herelog// console.log(a);leta; // The interpreter enters includeletBlock scope of variable statements. The variable immediately passes through the declaration phase, registering its name in scope, and // the interpreter then proceeds to parse the block statement line by line. console.log('########## - a', a); // initialize with undefined a='Reassigned'
  console.log('========= - a', a);

  console.log('########## - b', b);
  var b;
  b='b';
  console.log('========= - b', b);
}
console.log('Global A',a);
console.log('Global B', b);
Copy the code

Running results:

########## - a undefined========= -a is reassigned########## - b undefined========= - b b Global A 1 Global B bCopy the code

In the block-level scope, from the first line of the block-level scope to the line declaring variables with let variable, this area is the let’s temporary dead zone.

This temporary dead zone is in the Uninitialized State phase above, and an error is reported if the variable is accessed during this phase.

The let variable is accessible after Initialized State during the initialization phase.

1.3.1 whyHostingInvalid in the life cycle

As mentioned above, promotion is the coupling declaration and initialization of variables at the top. But the life cycle of the variables declared by let decouples the declaration and initialization phases. Decoupling eliminates the Hosting term let. The gap between the two phases creates a temporary dead zone where the variable cannot be accessed.

conclusion

The “creation” process of the LET has been improved, but initialization has not. Because the declaration and initialization phases are separate, promotion does not apply to let variables (including for const and class). Before initialization, the variable is in a time dead zone and inaccessible.

Here again:

If the initialization of let X fails, the x variable will always be declared. You cannot initialize x again (there is only one chance to initialize, and you failed that chance). Since x cannot be initialized, x is always in a temporary dead zone.