let and const commands
1. let
- concept:block scope。
- There is no variable promotion: if you use the variable before declaring it, an error will be reported.
- Temporary dead zone: A closed scope is formed. In the code block,
let
the variable is not available until the variable is declared. grammatically becomes"Temporary dead zone"(temporal dead zone, TDZ for short).
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 variable tmp is declared by the let command, it belongs to the "dead zone" of the variable tmp.
4. Do not allow repeated declarations: let
It is allowed to declare the same variable repeatedly in the same scope.
2. Block-level scope
1. Why do you need block-level scope?
In the first scenario, inner variables may override outer variables.
var tmp = new Date();
function f() {
//函数变量提升
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}
f(); // undefined
The original meaning of the above code is that if
the outside of the code block uses the outer layer tmp变量
, and the inner layer uses the inner layer tmp变量
. However, after the function f is executed, the output result is undefined
becausevariable hoisting, causing tmp
the variables in the inner layer to override tmp
the variables in the outer layer.
In the second scenario, the loop variable used for counting is leaked as a global variable. (very common)
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5
In the above code, the variable i
is only used to control the loop, but after the loop ends, it does not disappear and leaks into a global variable .
2. Block-level scope
let
Added for JavaScriptblock scope。
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}
Output 5 after running. This means that outer code blocks are not affected by inner code blocks. var
If the defined variable is used twice n
, the final output value is 10.
3. const
- Basic usage:
const
Declare a read-only constant. Once declared, the constant's value cannot be changed and must be assigned an initial value.
const PI = 3.1415;
PI // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.
const
Declared variables must not change value (referring to simple data types), which means,const
once a variable is declared, it mustinitialize immediately, cannot be left for later assignment.const
has the same scope aslet
a command: it is only valid within the block-level scope in which it is declared.const
The constants declared by the command are also not promoted, and there are alsotemporary dead zone, can only be used after the declared position.const
In fact, what is guaranteed 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 simple types of data (numbers, strings, Boolean values), the value is stored at the memory address pointed to by the variable, so it is equivalent to a constant. But for composite type data (mainly objects and arrays), the memory address pointed to by the variable is only a pointer to the actual data, and it can only be guaranteed that the pointer is fixed (that is, itconst
always points to another fixed address). As for whether the data structure it points to is mutable, it is completely out of control. Therefore, one must be very careful about declaring an object as a constant.
const foo = {
};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123
// 将 foo 指向另一个对象,就会报错
foo = {
}; // TypeError: "foo" is read-only
In the above code, the constant foo
stores an address, which points to an object. Only this address is immutable, that is, it cannot point foo
to another address, but the object itself is mutable, so new attributes can still be added to it.
Variable Destructuring Assignment
1. Array destructuring assignment
- Basic usage
Previously, to assign a value to a variable, you could only specify the value directly.
let a = 1;
let b = 2;
let c = 3;
ES6 allows it to be written like this.
let [a, b, c] = [1, 2, 3];
give many examples
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3
let [ , , third] = ["foo", "bar", "baz"];
third // "baz"
let [x, , y] = [1, 2, 3];
x // 1
y // 3
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
If the destructuring is unsuccessful, the value of the variable is equal to undefined
.
let [foo] = [];
// foo = undefined
let [bar, foo] = [1];
// foo = undefined
Another situation isincomplete deconstruction, that is, the pattern on the left side of the equal sign matches only a part of the array on the right side of the equal sign. In this case, deconstruction can still succeed.
let [x, y] = [1, 2, 3];
x // 1
y // 2
let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4
For Set
structures, you can also use the destructuring assignment of arrays.
let [x, y, z] = new Set(['a', 'b', 'c']);
x // "a"
- Defaults
Destructuring assignment allows default values to be specified.
let [foo = true] = [];
foo // true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
2. Object destructuring assignment
- Basic usage
let {
foo, bar } = {
foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"
Object destructuring differs from arrays in one important way. The elements of the array are arranged in order, and the value of the variable is determined by its position; while the properties of the object have no order, and the variable must have the same name as the property to get the correct value.
let {
bar, foo } = {
foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"
let {
baz } = {
foo: 'aaa', bar: 'bbb' };
baz // undefined
If destructuring fails, the value of the variable is equal to undefined
.
The destructuring assignment of an object can easily assign the method of an existing object to a variable.
// 例一
let {
log, sin, cos } = Math;
// 例二
const {
log } = console; // console.log
log('hello') // hello
Example 1 of the above code assigns Math
the logarithm, sine, and cosine methods of the object to the corresponding variables, which will be much more convenient to use. Example 2 will console.log
assign to log
the variable
actuallyThe internal mechanism of object deconstruction assignment is to first find the attribute with the same name, and then assign it to the corresponding variable. It is the latter that is actually assigned, not the former.
let {
foo: baz } = {
foo: 'aaa', bar: 'bbb' };
baz // "aaa"
foo // error: foo is not defined
In the above code, foo
the matching pattern baz
is the variable. What is actually assigned is the variable baz
, not the pattern foo
.
3. String destructuring assignment
Strings can also be destructured. This is because at this point, the string is converted into an array-like object.
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
4. Destructuring assignment of numeric and boolean values
When destructuring assignment, if the right side of the equal sign is a numeric value or a Boolean value, it will be converted to an object first.
let {
toString: s} = 123;
s === Number.prototype.toString // true
let {
toString: s} = true;
s === Boolean.prototype.toString // true
The rule of destructuring assignment is that as long as the value to the right of the equal sign is not an object or an array, convert it to an object first. Since undefined and null cannot be converted into objects, an error will be reported if they are deconstructed and assigned.
let {
prop: x } = undefined; // TypeError
let {
prop: y } = null; // TypeError
5. Purpose
(1) Exchange the value of the variable
let x = 1;
let y = 2;
[x, y] = [y, x];
(2) Returning multiple values from a function
A function can only return one value. If you want to return multiple values, you can only return them in an array or object. With destructuring assignment, it is very convenient to extract these values.
// 返回一个数组
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
// 返回一个对象
function example() {
return {
foo: 1,
bar: 2
};
}
let {
foo, bar } = example();
(3) Extract JSON data
Destructuring assignments are especially useful for extracting data in JSON objects.
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let {
id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]
(4) Traverse the Map structure
for...of
It is very convenient to traverse the loop and cooperate with the destructuring assignment of variables to obtain the key name and key value.
const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for (let [key, value] of map) {
console.log(key + " is " + value);
}
// first is hello
// second is world
(5)How to specify the input module
When loading a module, it is often necessary to specify which methods to import. Destructuring assignment makes the input statement very clear.
const {
SourceMapConsumer, SourceNode } = require("source-map");