The introduction
This article mainly introduces the meaning of var, let, const keywords, and from
- Scope rule
- Repeat declaration/repeat assignment
- Variable promotion (hoisted)
- Temporary Dead Zones (TDZ)
Var, let, and const are declared in four different ways
var
Before ES6 we defined JavaScript variables with the var keyword. The let and const keywords were added in ES6
var num = 1
Copy the code
Declare a variable in the global scope using var. By default, it is mounted under the top-level object Window (Node is global).
var num = 1
console.log(window.num) / / 1
Copy the code
The scope of a variable declared with VAR is its current execution context, which can be functional or global
var x = 1 // declare under global scope
function foo() {
var x = 2 // declare in the scope of foo
console.log(x) / / 2
}
foo()
console.log(x) / / 1
Copy the code
If x is not declared in foo, but is assigned, then x is assigned in the outer scope of foo
var x = 1 // declare under global scope
function foo() {
x = 2 / / assignment
console.log(x) / / 2
}
foo()
console.log(x) / / 2
Copy the code
If assigned to an undeclared variable, the variable is implicitly created as a global variable (it becomes a property of the top-level object)
a = 2
console.log(window.a) / / 2
function foo(){
b = 3
}
foo()
console.log(window.b) / / 3
Copy the code
Var defect 1: All variables that are not declared and assigned directly will be automatically hung under the top-level object, resulting in uncontrollable and chaotic global environment variables
Variable promotion (hoisted)
Variables declared using var may be promoted
console.log(b) // undefined
var b = 3
Copy the code
Note that promotion is only a variable declaration and does not affect the initialization of its value. It can be understood implicitly as:
var b
console.log(b) // undefined
b = 3
Copy the code
Scope rule
The var declaration can be accessed anywhere within the containing function, module, namespace, or global scope. The containing code block has no effect on this, so declaring the same variable more than once does not cause an error:
var x = 1
var x = 2
Copy the code
This scoping rule can cause some errors
function sumArr(arrList) {
var sum = 0;
for (var i = 0; i < arrList.length; i++) {
var arr = arrList[i];
for (var i = 0; i < arr.length; i++) { sum += arr[i]; }}return sum;
}
Copy the code
It’s easy to see the problem here, because the inner for loop overwrites variable I, because all I’s refer to variables in the same function scope. As experienced developers are well aware, these issues can be missed during code review and cause endless trouble.
Var defect 2: Allows multiple declarations of the same variable without an error, making the code difficult to maintain
Capture variable quirks
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6] ();/ / 10
Copy the code
I is the global variable, and there is only one global variable I. At the end of the for loop, I =10, so a[6]() is also 10, and I is 10 in all elements of A
Instead, we expect a[6]() to output 6, so we have the following block-level scope
let
Let is written the same way as var, except that it uses block scope
let a = 1
Copy the code
Block-scoped variables are not accessible outside the block or for loop that contains them
{
let x = 1
}
console.log(x) // Uncaught ReferenceError: x is not defined
Copy the code
So:
var a = [];
for (let i = 0; i < 10; i++) { // Each loop I is a new variable
a[i] = function () {
console.log(i);
};
} // The JavaScript engine internally remembers the value of the previous cycle, and when it initializes the variable I of this cycle, it evaluates on the basis of the previous cycle
a[6] ();/ / 6
Copy the code
At the same time, let solves two defects of VAR:
Variables declared under the global scope using let are also not attributes of the top-level object
let b = 2
window.b // undefined
Copy the code
Then where is it?
var a = 1
let b = 2
debugger
Copy the code
As you can also see from the figure above, global variables declared with lets and const are not in the global object, but in a block-level scope (Script)
Duplicate declarations are not allowed in the same block
let x = 1
let x = 2
// Uncaught SyntaxError: Identifier 'x' has already been declared
Copy the code
It can be declared if it’s in different blocks
{
let x = 1
{
let x = 2}}Copy the code
This behavior of declaring the same variable name in a nested scope is called masking, and it perfectly solves the sumArr problem above:
function sumArr(arrList) {
let sum = 0;
for (let i = 0; i < arrList.length; i++) {
var arr = arrList[i];
for (let i = 0; i < arr.length; i++) { sum += arr[i]; }}return sum;
}
Copy the code
I’ll get the right answer, because I in the inner loop can mask I in the outer loop
Masking should generally be avoided because we need to write clean code. There are also scenarios where you can use it, and you need to think about it
Temporary Dead Zones (TDZ)
A variable declared by a let cannot be accessed until it is declared
console.log(x) // Uncaught ReferenceError: x is not defined
let x = 1
Copy the code
If you declare let in a block, it will report the following error:
// let
{
console.log(x) // Uncaught ReferenceError: Cannot access 'x' before initialization
let x = 2
}
Copy the code
That is, if the error content is uninitialized in the block-level scope, is the let promoted in the block-level scope?
In reactors-VS-TDZ. MD, TC39 member Rick Waldron puts it this way:
In JavaScript, all binding declarations are instantiated when control flow enters the scope in which they appear. Legacy var and function declarations allow access to those bindings before the actual declaration, with a “value” of
undefined
. That legacy behavior is known as “hoisting”. let and const binding declarations are also instantiated when control flow enters the scope in which they appear, with access prevented until the actual declaration is reached; this is called the Temporal Dead Zone. The TDZ exists to prevent the sort of bugs that legacy hoisting can create.
Translation:
In JavaScript, all binding declarations are instantiated when the control flow enters the scope where they appear. Traditional var and function declarations allow access to those bindings before they are actually declared, and their value is undefined. This legacy behavior is known as variable promotion. Let and const declarations are also instantiated when the control flow enters the scope where they occur, but access is denied until the actual declaration is run. This is called a Temporal Dead Zone. TDZ exists to prevent the kind of errors that traditional ascension can cause.
That is, let/const variables are always “present” in their scope, but cannot be accessed before let/const statements, so they are not called variable promotions, only temporary dead zones
const
Const declares a read-only constant. Once declared, the value of a constant cannot be changed.
const a = 1
a = 2 // Uncaught TypeError: Assignment to constant variable.
Copy the code
Therefore, a variable declared by const may not change its value, which means that a const, once declared, must be initialized immediately and cannot be left for later assignment.
const s // Declare no value assigned
// Uncaught SyntaxError: Missing initializer in const declaration
Copy the code
Note that const does not guarantee that the value of the variable is fixed, but that the memory address to which the variable refers is fixed. For primitive types, the value of the variable is stored at that memory address, where it is always on. For reference types, its internal value can be changed
const num = 1
const user = {
name: "sisterAn".age: num,
}
user = {
name: "pingzi".age: num
} // Uncaught TypeError: Assignment to constant variable.
// All of the following are running successfully
user.name = "Hello"
user.name = "Kitty"
user.name = "Cat"
user.age--
Copy the code
Other const is the same as let, for example:
- Same scope, valid only in the block-level scope of the declaration
- Constants also do not ascend and also have temporary dead zones
I won’t repeat it here
var vs let vs const
Var, let, and const differ in the following ways:
- Scope rule
- Repeat declaration/repeat assignment
- Variable promotion (hoisted)
- Temporary Dead Zones (TDZ)
Scope rule
Variables declared by let/const are block-scoped and are only available in their blocks or subblocks. The scope of a variable declared by var can be global or the whole enclosing function
Repeat declaration/repeat assignment
var
Repeated declarations and repeated assignments are possiblelet
Only repeated assignments are allowed, but no repeated declarations are allowedconst
Neither assignment nor declaration can be repeated
Variable promotion (hoisted)
The variable declared by var has variable promotion, that is, it can be accessed before the variable is declared, and its value is undefined
Let and const do not have variable promotion, that is, the variables they declare must be used after declaration, otherwise ReferenceError is reported
Var:
console.log(a) // undefined
var a = 1
Copy the code
Let:
console.log(b) // Uncaught ReferenceError: b is not defined
let b = 2
Copy the code
Const:
console.log(c) // Uncaught ReferenceError: c is not defined
let c = 3
Copy the code
Temporary Dead Zones (TDZ)
Var does not have a temporary dead band. Let and const have a temporary dead band and can only be accessed or used after a variable has been declared
Programming style
ES6 introduced two new commands to declare variables: let and const. Among them, let can completely replace VAR because the semantics are the same and let has no side effects. Therefore, we recommend using let and const instead of var in our development
reference
- MDN
- Ruan Yifeng: An Introduction to ECMAScript 6
Three minutes a day