Article Directory
Preface: The drawbacks of var declaration variables in ES5
ES5 actually provides us with two methods of declaring variables: var
commands and function
commands. Using function
commands to declare functions is not discussed here, we mainly compare var
commands.
Earlier, we explained in detail in the JS Getting Started article that var
there are three major characteristics of command declaration variables:
- Variables can be declared repeatedly;
- Variable declarations will be promoted;
- No block-level scope;
These three characteristics make the writing of JS code seem a bit "random" and not standardized enough, and such grammatical logic is also counterintuitive. Give two examples:
- The inner variable will cover the outer variable
with the same name: Below wevar
declare a global variable andnum
assign a value of 1, and then redeclare the variableshow
in theif
code block of the function scopenum
, and assign a value of 2:
var num = 1;
function show() {
console.log(num);
if (false) {
var num = 2;
}
}
show();
——————OUTPUT——————
undefined
The final show
function execution output result is undefined
.
This is because the var
declared variable has no block-level scope. The second redeclaration num
will be promoted to the beginning of the function, covering the outer global variable with the same name. At this time, the output result must be undefined
. (All three characteristics are reflected in one example)
- The loop variables used for counting in various loop structures will be leaked as global variables: when
we use loop structures, we will declare a loop control variable (such as i, j, k, etc.), but after the loop ends, it does not disappear , Leaked into a global variable.
for (var i = 0; i < 3; i++) {
//...
}
console.log(i);
——————OUTPUT——————
2
A better approach is that we want it to be valid only in the loop control, and it will automatically fail after the loop ends and will not affect the execution of other parts of the code. At this time, we need to use the new let
commands in our ES6 .
1. Let and const basics
1.1 Basic usage of let
let
Commands are new commands used to declare variables in the ES6 standard. Its mission is to replace var
commands. Its usage is similar var
, but it makes up var
for design flaws.
The most fundamental difference between the two is that the let
command can declare the current code block as a block-level scope (detailed in subsequent chapters), and let
the variables declared by the command are only valid in the current code block.
(The code block is in a pair of curly braces {}
)
{
let a = 1;
var b = 2;
}
a // ReferenceError: a is not defined.
b // 2
Access the variable outside the block of code a
will be reported undefined error while using var
defined b
variables can still be accessed.
Now with the let
command, you can solve the second problem at the beginning of this article: the problem of loop variable leakage. We use the statement of the for
loop counter :i
let
for (let i = 0; i < 3; i++) {
//...
}
console.log(i);
——————OUTPUT——————
// ReferenceError: i is not defined
The variable i
is not accessible at this time .
❀ Expand a bit (1) ❀
let
There is another point to note when using commands in loops: variables i
will be redeclared each time in the loop .
Let's first look at using the var
declared loop variable i
, and add a timer function to print out this loop variable in each loop i
:
for(var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
——————OUTPUT——————
3
3
3
Three 3s are output because the loop variable in the entire for loop is i
always the same variable, and finally the loop end variable i
is assigned the value 2. Then change to the let
command and output it again:
for(let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
——————OUTPUT——————
0
1
2
You can see that the output result is the same as without the timer function. This is because the variable i
is re-declared every time in the loop. The reason why it is output according to the normal logic is that the JavaScript engine will remember the value of the previous round of loop. , When initializing the variables of this round, the i
calculation is performed on the basis of the previous round.
❀ Expand a bit (2) ❀
The for loop itself has another special feature- the part that sets the loop variable is a parent scope, and the inside of the loop body is a separate child scope.
for (let i = 0; i < 3; i++) {
let i = 'zevin';
console.log(i);
}
——————OUTPUT——————
zevin
zevin
zevin
It was output 3 times zevin
. This shows that the variables inside the loop body i
and the loop variables i
are not in the same scope, and have their own separate scopes.
1.2 Basic usage of const
const
The command is used to declare a read-only constant. It must be assigned at the beginning of the declaration, and cannot be changed once declared.
const PI;
// SyntaxError: Missing initializer in const declaration
const PI = 3.1415926;
PI = 3.14;
// TypeError: Assignment to constant variable.
❀ Expand it ❀
The essence of the const command
What the const command actually guarantees is not that the value of the variable cannot be changed, but that the data stored in the memory address pointed to by the variable cannot be changed.
For basic types of simple data (numerical value, string, Boolean value), the memory address pointed to by the variable stores the value itself, so it is equivalent to the value of the variable that cannot be modified;
const obj = {
};
// 可以添加属性
obj.name = 'zevin';
console.log(obj.name);
// zevin
// 让obj指向另一个对象就会报错
foo = {
};
// TypeError: "obj" is read-only
For reference data types (mainly arrays, objects), the memory address pointed to by the variable saves the reference address, but the reference address cannot be changed. For the array, the object itself, we can still add or delete element.
2. ES6 variable declaration new specification
In order to improve the situation in a statement ES5 var command, but also in order to improve the normative JS language, ES6 proposes the following four new variable declaration norms, let
and const
commands are applicable.
2.1 Block-level scope
ES5 has only global scope and function scope. Finally, block-level scope has been added to ES6. Use let
or const
block-level action command variable declared in a statement only where the domain is valid.
{
let a = 1;
if(true){
const a = 2;
};
console.log(a);
}
——————OUTPUT——————
1
The code block is based on a pair of curly braces {}
, which can be nested arbitrarily without affecting each other.
{
{
{
{
{
const name = 'zevin' }
console.log(name);
// 报错
}}}};
The above code uses a five-level block-level scope, each of which is a separate scope. The fourth-level scope cannot read the internal variables of the fifth-level scope.
2.2 There is no variable promotion
var
The variable declared by the command will be promoted to the beginning of the document or the beginning of the function, that is, the variable can be used before the declaration, and the value is undefined
. And fixed the grammar in behavior ES6, let
and const
variable command must be declared in a statement after use, otherwise an error.
console.log(a);
console.log(b);
console.log(c);
var a = 1;
let b = 2;
const c = 3;
——————OUTPUT——————
undefined
ReferenceError: Cannot access 'b' before initialization
ReferenceError: Cannot access 'c' before initialization
2.3 Temporary dead zone
ES6 clear that, if the block exists let
and const
command, this block these commands variable declarations, from the outset to form a closed scope. If these variables are used before the declaration, an error will be reported. This is grammatically called "temporal dead zone" (TDZ).
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
In the above code, before the let
command declares the variable tmp
, all belong to tmp
the "dead zone" of the variable .
❀ Expand it ❀
The emergence of "temporary dead zone" also means that it is typeof
no longer an operation that will never report errors.
typeof a; // undefined
typeof b; // ReferenceError
const b = 1;
Variable b
use const
before declaring variables belong to b
the "dead zone", as long as the use that variable error. Therefore, the typeof
operator will throw an ReferenceError
error.
But if a variable is not declared (variable a
) at all, typeof
it will not report an error when used undefined
.
2.4 Duplicate declarations are not allowed
ES6 does not allow multiple declarations of the same variable in the same scope.
if(true){
var a = 1;
let a = 2;
const a = 3;
}
// SyntaxError: Identifier 'a' has already been declared
Therefore, in the same way, the variable with the same name as the formal parameter cannot be used let
or const
commanded in the function , but it var
can.
function func(num) {
let num = 1;
console.log(num);
}
func()
// SyntaxError: Identifier 'num' has already been declared
function func(num) {
var num = 1;
console.log(num);
}
func()
// 1
Since different block-level scopes do not affect each other, we can define variables with the same name in different block-level scopes. So the following code will not report an error:
function func(num) {
var num = 1;
if(true){
let num = 2;
}else{
const num =3;
}
}
func()
3. Extension: Six ways to declare variables in ES6
ES5 | ES6 |
---|---|
var function |
let const import class |
ES6 in fact, four new variable declaration methods: This paper introduces the let
commands and const
command, follow-introduced again import
commands and class
command. Coupled with the var
commands and function
commands in ES5 , there are six ways to declare variables in ES6.