解构赋值时ES6
中很好用的一个特性,很多场景都会使用到。
变量的解构赋值
数组的解构赋值
let [a, b, c] = [1, 2, 3];
解构不成功,变量的值就等于undefined
。
let [foo, [[bar], baz]] = [1, [[2], 3]]; // bar 为 2
let [ , , third] = ["foo", "bar", "baz"]; // third 为 "baz"
let [head, ...tail] = [1, 2, 3, 4]; // tail 为 [2, 3, 4]
let [x, y, ...z] = ['a']; // y 为 undefined z为一个空数组[]
let [x, y] = [1, 2, 3]; // 不完全解构
let [x, y, z] = new Set(['a', 'b', 'c']); // Set的解构赋值
数组解构赋值的条件:如果等号的右边不是可遍历的结构将会报错,要某种数据结构具有 Iterator
接口,都可以采用数组形式的解构赋值。
解构赋值可以指定默认值。
只有当一个数组成员严格等于undefined
,默认值才会生效
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
let [x = y, y = 1] = []; // ReferenceError: y is not defined
对象的解构赋值
对象的解构,变量必须与属性同名,才能取到正确的值,并不是看顺序,顺序可以不一样
如果解构失败,变量的值等于undefined
。
对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。
const { log } = console; // 将console对象的log方法赋值给log变量
log('hello') // hello
如果变量名与属性名不一致,必须写成下面这样。
let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; // 使用foo找到值,赋值给baz变量
baz // "aaa"
foo // error: foo is not defined
对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。 比如说上面的foo
就报错了。上面的foo
叫做模式,baz
叫做变量。
当解构赋值用于嵌套对象的时候一定要分清哪里是模式,哪里是变量,一般嵌套的最内层是变量,外层全是模式,像下面这样:
const node = {
loc: {
start: {
line: 1,
column: 5
}
}
};
let { loc, loc: { start }, loc: { start: { line }} } = node;
line // 1
loc // Object {start: Object}
start // Object {line: 1, column: 5}
上面的三次赋值,分别赋值了loc
,start
,line
可以把值赋值给其他对象或数组:
let obj = {};
let arr = [];
({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });
obj // {prop:123}
arr // [true]
如果解构模式是嵌套的对象,但是子对象所对应的父属性不存在,那么将会报错。
对象的解构赋值可以取到继承的属性。
对象解构赋值的默认值
对象的解构也可以指定默认值,只要给变量指定默认值就行,不要把默认值指定给了模式。 默认值生效的条件是,对象的属性值严格等于undefined
。
解构赋值的注意点
- 如果要将一个已经声明的变量用于解构赋值,必须非常小心 。
// 正确的写法
let x;
({x} = {x: 1});
如果不加上面的圆括号就会报错。
-
解构赋值允许等号左边的模式之中,不放置任何变量名,空空如也。
-
由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr; // 方括号中属于“属性名表达式”
first // 1
last // 3
字符串的解构赋值
let {length : len} = 'hello';
len // 5
数值和布尔值的解构赋值
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined
和null
无法转为对象,所以对它们进行解构赋值,都会报错。
函数参数的解构赋值
下面的写法很骚,但是很实用。
[[1, 2], [3, 4]].map(([a, b]) => a + b);
函数参数的解构也可以使用默认值,这个在函数扩展那一章节里面有讲。
解构赋值中使用圆括号
可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。
首先是赋值语句,而不是声明语句(let
, var
...);其次它们的圆括号都不属于模式的一部分(模式上面有说)。
解构赋值的骚操作
交换变量的值
let x = 1;
let y = 2;
[x, y] = [y, x];
从函数返回多个值
函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。
函数参数的定义
解构赋值可以方便地将一组参数与变量名对应起来,比如说赋值给一个方法的参数为一个对象,这个时候可以使用解构赋值来拆分为多个参数。
提取 JSON 数据
服务器返回一个JSON数据,就可以使用解构赋值,更加方便的获取需要的值。
函数参数的默认值
可以使用解构赋值的默认值来为函数的参数指定默认值。
遍历 Map 结构
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
// 只获取键名
for (let [key] of map) {
// ...
}
// 只获取键值
for (let [,value] of map) {
// ...
}
输入模块的指定方法
这个在模块开发中很常用。
const { SourceMapConsumer, SourceNode } = require("source-map");