数组的解构赋值:
- ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。
let [a, b, c] = [1, 2, 3];
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。而这种模式不需要完全匹配,只要匹配一部分也是可以的。
如果等号的右边不是数组(或者严格地说,不是可遍历的结构,参见《Iterator》一章),那么将会报错。而set则是可遍历的结构。
- 允许指定默认值,但是仅当数组对应的成员===undefined时才会生效。如下例,是null的时候仍然会赋值成功。
let [x = 1] = [undefined];
x // 1
let [x = 1] = [null];
x // null
如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。
默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
对象的解构赋值
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
必须要属性名一致
let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };
ES6 的简写方法,如果对象的属性名和值一样则可以用foo代替foo:foo;
- 对象的解构也可以指定默认值。
默认值生效的条件是,对象的属性值严格等于undefined。 - 如果解构失败,变量的值等于undefined。
- 如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。因为foo这时等于undefined,再取子属性就会报错
let {foo: {bar}} = {baz: 'baz'};
- 如果要将一个已经声明的变量用于解构赋值,必须非常小心。
要避免JS引擎把 {} 理解为代码块
let x;
({x} = {x: 1});
- 对数组(特殊的对象)也可以进行这样的结构:
对应的key是下标值。
字符串解构赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
其length也可以作为一个key值进行解构。
数值或布尔值的解构赋值
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。先转成对象再调用其tostring方法,由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
函数参数的解构赋值
函数的参数也可以使用解构赋值。
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
上面代码中,函数add的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量x和y
注意区分这两种写法:
- 前者代码中,函数move的参数是一个对象,通过对这个对象进行解构,得到变量x和y的值。如果解构失败,x和y等于默认值。
- 后者代码是为函数move的参数指定默认值,而不是为变量x和y指定默认值,所以会得到与前一种写法不同的结果。
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]
function move({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]
圆括号的禁止使用情况
(1)变量声明语句
(2)函数参数
(3)赋值语句的模式
可以使用的只有一种情况:赋值语句的非模式部分,可以使用圆括号。
如:
[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确
解构赋值的用途
- swap
let x = 1;
let y = 2;
[x, y] = [y, x];
- 函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
- 解构赋值可以方便地将一组参数与变量名对应起来。
// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);
// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});
- 解构赋值对提取 JSON 对象中的数据,尤其有用。
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]
- 指定参数的默认值
jQuery.ajax = function (url, {
async = true,
beforeSend = function () {},
cache = true,
complete = function () {},
crossDomain = false,
global = true,
// ... more config
} = {}) {
// ... do stuff
};
- 用这种方式遍历(也有些像vue的结构)
for (let [key, value] of map)