“This is the first day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Variable promotion (as)

We can write JavaScript code like this without error, and the variable will be promoted to the top of the current scope.

console.log(a) // undefined
var a = 1
Copy the code

The reason for this is that aT runtime, JavaScript reapplies the variable A declared with the var command to the top of the current scope. Is equivalent to

var a
console.log(a) // undefined
a = 1
Copy the code

In the following code, when the variable A is declared using the var command, the variable will be prompted (in case of reactive power loss).

console.log(a) // ReferenceError: a is not defined
let a = 1
Copy the code

ReferenceError: A is not defined. At this time, it appears that there is no variable promotion (in case of reactive power). So what’s the real story? If LET doesn’t create a reactive power, why am I being laughed at by the big shots?

Look for the answer in the little Red Book

Let’s take a look at the Little Red Book for an answer.

Var declaration enhancement

Variable 3.3 is introduced in the Little Red BookvarDeclared promoted

In general, this is the same as WHAT I said, but it describes how to use var to declare the same variable in case of variable promotion.

var a = 0
var a = 1
var a = 2
console.log(a) / / 2
Copy the code

At JavaScript runtime this would be equivalent to the following code

var a = 0
a = 1
a = 2
console.log(a) / / 2
Copy the code

Let temporal dead zone

Variable 3.3 in the Little Red Book is introduced as follows: Let mentioned a new concept temporal dead zone.

When you use a declaration variable in a LET, JavaScript runtime will notice the following let declaration, but it cannot be referenced. So this is called temporal dead zone. ReferenceError: XXX is not defined if we use an undeclared variable.

However, in the little Red Book # 4 4.2.2 variable declaration it is strictly stated that let is also promoted in JavaScript runtime. Is there a mistake in the Little Red Book that leads to a different story?

A closer look reveals no conflict between the two statements:

  1. Another important difference between let and var is that the variables declared by let are not inscopeBe promoted in.
  2. Strictly speaking, let isThe JavaScript runtimeIs also promoted, but because of the “temporal dead zone”, you can’t actually use the let variable before the declaration.

The summary at this point might be that let is not promoted directly to the top of the current scope, and variables declared by let cannot be used before declaration due to “temporal dead zone”.

Advanced the

let

According to the above reading and analysis of the Little Red Book, we can roughly understand that LET will cause variable promotion (as), but it is different from that of VAR. It cannot be used because of the “temporal dead zone”. But many issues remain unclear, such as how temporal dead zones arise. The answer to this question may be found in the ecma262.

Ecma262’s 14.3.1 Let and Const Declarations contains these statements:

let and const declarations define variables that are scoped to the running execution context’s LexicalEnvironment.

LexicalEnvironment that defines scoped variables to the running execution context via let and const declarations

The variables are created when their containing Environment Record is instantiated but may not be accessed in any way until the variable’s LexicalBinding is evaluated.

Variables are created by the LexicalEnvironment at instantiation time but are not yet accessible because of lexical binding.

If a LexicalBinding in a let declaration does not have an Initializer the variable is assigned the value undefined when The LexicalBinding is Evaluated.

A LexicalBinding assigns the value of undefined to a variable if the LexicalBinding is not assigned at initialization.

Let declares variables in JavaScript runtime. The creation process is completed first in the LexicalEnvironment and cannot be accessed at this point. It can only be accessed after initial assignment and LexicalBinding. Initialization without an assignment will default to undefined.

Simulate the case when no assignment is made at initialization

let a
console.log(a) // undefined
Copy the code

Simulate an initial assignment

let a = 1
console.log(a) / / 1
Copy the code

It is understood that an error cannot be accessed while the initialization is incomplete. But the LexicalEnvironment was mentioned, so throwing errors should be expanded in the LexicalEnvironment

Ecma262 9.1.1 The Environment Record Type Hierarchy

If the binding exists but is uninitialized a ReferenceError is thrown, regardless of the value of S.

ReferenceError is raised if the binding should not have completed initialization of the value.

The overall process is as follows:

var

Ecma262’s 14.3.2 Variable Statement contains these sentences:

Var variables are created when their containing Environment Record is instantiated and are initialized to undefined when created

A variable declared by var is initialized first in the LexicalEnvironment. If no value is assigned during initialization, it defaults to undefined.

In simple terms, the var creation phase and the initialization phase are completed at the same time, and directly into the assignment phase

The overall process is as follows:

const

Ecma262 14.3.1.1 Static Semantics: Early Errors

It is a Syntax Error if Initializer is not present and IsConstantDeclaration of the LexicalDeclaration containing this LexicalBinding is true.

If a constant is not assigned during the binding phase, it is a syntax error

The Runtime Semantics: Evaluation ecMA262 14.3.1.2 Runtime Semantics: Evaluation

A static semantics rule ensures that this form of LexicalBinding never occurs in a const declaration..

Static semantic rules ensure that const declarations cannot have duplicate binding assignments

conclusion

As of July 1, 1997, let will cause variable promotion (as of July 1, 1997) in use. According to the Little Red Book with ecMA262, strictly speaking, the let upgrade is only an upgrade to the creation phase, which is not yet accessible. ReferenceError will be raised if an unsolicited access is made. Var is promoted because the var creation phase and the initialization phase are merged into one and the assignment phase is accessed directly.

One day

Ecma262 14.3.1.1 Static Semantics: Early Errors

It is a Syntax Error if the BoundNames of BindingList contains “let”.

An error is reported if a variable in the binding list has a let

let let = 1 // Uncaught SyntaxError: let is disallowed as a lexically bound name
Copy the code

Var or const will also return an error, but the content of the error is different

let var = 1 // Uncaught SyntaxError: Unexpected token 'var'
Copy the code

Here is the end of this analysis, see the head dizzy, do not say to go to sleep. Before going to bed, I also bother you to move your little hands. Of course, you are welcome to leave your comments below.