什么是解构:ES6允许按照一定的模式,从数组或者对象中提取值,然后赋值给相应变量,此为解构。
1.数组的解构赋值
解构分为完全解构和不完全解构,前者要求一一对应,后者可以是等号左边只匹配等号右边的一部分。解构不成功会返回undefined。
let [foo] = [];
alert(foo); // undefined
重点:不是只有数组才可以解构赋值,只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值。
function* fibs() {
let a = 0;
let b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
let [first, second, third, fourth, fifth, sixth] = fibs();
sixth // 5
fibs是一个Generator函数(生成器)
默认值
上面代码中,如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined。
let [x = 1] = [undefined];
x // 1
let [x = 1] = [null];
x // null
默认值还可以是一个表达式,表达式只有用到的时候才会求值
function f() {
console.log('aaa');
}
let [x = f()] = [1];
默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
let [x = 1, y = x] = []; // x=1; y=1
let [x = 1, y = x] = [2]; // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = []; // ReferenceError: y is not defined
2.对象的解构赋值
对象的解构赋值和数组的不同之处在于对象是根据key-value查找key值来赋值的,和顺序没关系。如果解构失败返回undefined。
// 例一
let { log, sin, cos } = Math;
// 例二
const { log } = console;
log('hello') // hello
上面代码的例一将Math对象的对数、正弦、余弦三个方法,赋值到对应的变量上,使用起来就会方便很多。例二将console.log赋值到log变量。
let obj = {first:'hello',last:'world'};
let {first:f,last:l} = obj;
alert(f+l); //helloworld
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
alert(baz); // aaa
对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。前者是模式,后者才是变量。
设置继承关系,obj1继承自obj2
const obj1 = {};
const obj2 = {foo:'bar'};
Object.setPrototypeOf(obj1,obj2);
const {foo} = obj1;
alert(foo);
3.字符串的解构赋值
字符串的解构赋值会被转换成一个类似数组的对象。其有一个length属性。
const [a,b,c,d,e] = 'hello';
alert(a);
let {length : len} = 'hello';
alert(len);
4.数值和布尔值的解构赋值
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
5.函数参数的解构赋值
函数的参数可以使用数组,也可以是对象。参数可以使用默认值。
数组:
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
对象:
为变量指定默认值
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]
6.可以使用圆括号的情况
可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。
[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确
上面三行语句都可以正确执行,因为首先它们都是赋值语句,而不是声明语句;其次它们的圆括号都不属于模式的一部分。第一行语句中,模式是取数组的第一个成员,跟圆括号无关;第二行语句中,模式是p,而不是d;第三行语句与第一行语句的性质一致。
7.解构赋值的用途(常用的要熟记)
主要是针对数组,对象的解构赋值进行应用,比如:
1.交换变量的值
2.从函数返回多个值
3.向函数传参
4.提取JSON数据
5.函数参数的默认值
6.遍历Map解构
7.输入模块的指定方法
const { SourceMapConsumer, SourceNode } = require("source-map");