ECMAScript6入门笔记2-变量的解构赋值

记录一下阅读阮老师的《ECMAScript 6入门》,本篇包含的内容:变量的解构赋值。

数组的解构赋值

基本用法

ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

1
2
// 解构赋值不仅适用于var命令,也适用于let和const命令。
var [a, b, c] = [1, 2, 3];

如果解构不成功(也就是模式没配对上),变量的值就等于undefined。
如果等号的右边不是数组,那么将会报错。

1
2
3
4
// 对于Set结构,也可以使用数组的解构赋值。
let [x, y, z] = new Set(["a", "b", "c"]);
x // "a"

默认值

解构赋值允许指定默认值。ES6内部使用严格相等运算符(===),判断一个位置是否有值。如果一个数组成员不严格等于undefined,默认值是不会生效的。

1
2
3
4
5
var [x = 1] = [undefined];
x // 1

var [x = 1] = [null];
x // null

如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。

1
2
3
4
5
6
function f() {
console.log('aaa');
}

let [x = f()] = [1];
x //1

默认值可以引用解构赋值的其他变量,但该变量必须已经声明。

对象的解构赋值

对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

1
2
3
4
5
6
var { bar, foo } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"

var { baz } = { foo: "aaa", bar: "bbb" };
baz // undefined

对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。

1
2
3
var { foo: baz } = { foo: "aaa", bar: "bbb" };
baz // "aaa"
foo // error: foo is not defined

注意,采用这种写法时,变量的声明和赋值是一体的。对于let和const来说,变量不能重新声明,所以一旦赋值的变量以前声明过,就会报错。

1
2
3
4
5
6
let foo;
let {foo} = {foo: 1}; // SyntaxError: Duplicate declaration "foo"

// 可以使用如下写法,不加圆括号会导致报错
let foo;
({foo} = {foo: 1}); // 成功

和数组一样,解构也可以用于嵌套结构的对象。

1
2
3
4
5
6
7
8
9
10
11
var obj = {
p: [
'Hello',
{ y: 'World' }
]
};

var { p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // p is not defined. 因为此时p为模式,并没有为其赋值

对象的解构可以指定默认值(规则与数组类似)。

由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。

1
2
3
4
var arr = [1, 2, 3];
var {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3

字符串的解构赋值

字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。

1
2
3
4
5
6
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。

1
2
let {length : len} = 'hello';
len // 5

数值和布尔值的解构赋值

解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。如果不能转为对象会报错,例如nullundefined

1
2
3
4
5
let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true

函数参数的解构赋值

函数参数的解构也可以使用默认值。

1
2
3
4
5
6
7
8
function move({x = 0, y = 0} = {}) {
return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]

圆括号问题

不能使用圆括号的情况:

(1)变量声明语句中,不能带有圆括号。
(2)函数参数中,模式不能带有圆括号。
(3)赋值语句中,不能将整个模式,或嵌套模式中的一层,放在圆括号之中。

可以使用圆括号的情况:

只有一种: 赋值语句的非模式部分,可以使用圆括号。

解构赋值的用途

(1)交换变量的值
(2)从函数返回多个值
(3)函数参数的定义
(4)提取JSON数据
(5)函数参数的默认值
(6)遍历Map结构
(7)输入模块的指定方法