什么是解构赋值?
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
// MDN官方
let a, b, rest;
[a, b] = [10, 20];
console.log(a);
// expected output: 10
console.log(b);
// expected output: 20
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(rest);
// expected output: Array [30,40,50]
数组的解构赋值
// 解构成功
let [a, b, c] = [1, 2, 3]; a 1,b 2,c 3
let [foo, [[bar], baz]] = [1, [[2,4], 3]]; // foo 1,bar 2,baz 3
let [ , , third] = ["foo", "bar", "baz"]; // third "baz"
let [head, ...tail] = [1, 2, 3, 4]; // head 1,tail [2,3,4]
// 解构失败
let [foo] = []; // foo undefined
let [bar, foo] = [1]; // foo undefined
// 只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值。反之解构失败
// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
// 允许默认值
let [a,b=2] = [1] // a = 1,b = 2
let [x = f()] = [1]; // 默认值是表达式,表达式是惰性求值的,只有用到才会求值。
// 默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
let [x = 1, y = x] = []; // x=1; y=1
对象的解构赋值
// 数组解构依赖于顺序,但是对象解构依赖于key,下面二者等价,解构失败的为undefined
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
let { foo, bar } = { bar: 'bbb', foo: 'aaa' };
// 嵌套对象的解构
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};
let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]
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}
字符串的解构赋值
const [a, b, c, d, e] = 'hello';
函数参数解构
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]
不能使用圆括号的情况
// 变量声明语句 全部报错
let [(a)] = [1];
let {x: (c)} = {};
let ({x: c}) = {};
let {(x: c)} = {};
let {(x): c} = {};
let { o: ({ p: p }) } = { o: { p: 2 } };
// 函数参数
// 报错
function f([(z)]) { return z; }
// 报错
function f([z,(x)]) { return x; }
// 赋值语句
({ p: a }) = { p: 42 };
([a]) = [5];
// 总之,只要有解构歧义的可能,就不要带()。
// 赋值语句的非模式部分,可以使用圆括号。
[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确
解构用途
// 交换变量的值 类似python语法了
let x = 1;
let y = 2;
[x, y] = [y, x];
// 从函数返回多个值
// 返回一个数组
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
// 返回一个对象
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = 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;
// 函数参数的默认值
jQuery.ajax = function (url, {
async = true,
beforeSend = function () {},
cache = true,
complete = function () {},
crossDomain = false,
global = true,
// ... more config
} = {}) {
// ... do stuff
};
// 遍历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
//引入模块的指定方法
const { SourceMapConsumer, SourceNode } = require("source-map");
import {x,xx,xxx} from 'xx'
参考:
- 阮一峰老师《ES6标准入门 第三版》
- MDN Destructuring assignment