数组的解构赋值
ES6允许按照一定的模式从数组和对象中取值,然后对变量进行赋值,这种操作被称为解构.
比如我们以前为一些变量赋值的时候,只能声明一个变量赋值一个变量,如下:
let a = 1;
let b = 2;
let c = 3;
这样的操作有很简单,但也有规律性,就是只是声明了一些简单的变量然后为其赋值.到了ES6之后,有了新的标准和技术实现方案,可以简化这些操作:
let [a,b,c] = [1,2,3];
这种写法,属于模式匹配,即只要等号(=)两边的模式相同,等号左边的变量就会被赋予对应的值.
let [a,[[b],c]] = [1,[[2],3]];
a //1
b //2
c //3
如果解构失败,那么变量的值会被设置为默认值undefined.
let [a] = [];
console.log(a); //undefined
不完全解构:等号左边的模式只匹配一部分等号右边的数组,这个时候也可以解构成功,只是等号右边的数组中的值没有被完全赋值到左边的变量中.
let [a,[b,c]] = [1,[2],3];
console.log(a); //undefined
console.log(b); //2
console.log(c); //undefined
左侧的模式c没有匹配到右侧的值,而右侧有一个值3,在左侧也没有模式与之匹配,但这种情况都可以匹配成功,只是这种情况下,左侧的模式c没有在右侧找到对应的匹配值,右侧的值3也没有在左侧找到与之匹配的模式.这种情况就称作不完全解构.
但是如果等号的右边不是数组(严格来说,应该是不可遍历的解构,因为还有对象的解构),那么解构会报错.
let [a] = 12;
let [b] = false;
let [c] = null;
let [d] = undefined;
let [e] = NaN;
let [f] = {};
这几种情况下的解构都会报错,如{} is not iterable,原因就是等号右侧的值活转换为对象后不具备iterable接口,是不可遍历的.
默认值
解构赋值允许指定默认值.
let [a = 12,b] = [];
console.log(a); //12
console.log(b); //undefined
let [a,b = 12] = [11]
console.log(a); //11
console.log(b); //12
在解构赋值中,只有当数组中的值严格等于undefined的时候,默认值才会生效.
let [a = 1] = [undefined];
console.log(a); //1
let [b = 2] = [null];
console.log(b); //2 null不是严格等于undefined,所以默认值没有生效
如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在使用到默认值的时候,这个表达式才会执行.
function f(){
return "Hello world";
}
let [c = f()] = [1];
console.log(c); //1 等号有面有值与左侧的模式c匹配,所以默认值表达式并没有执行
function f(){
return "Hello world";
}
let [c = f()] = [1];
console.log(c); //Hello world 因为等号有面没有值与模式c匹配,所以使用了默认值
默认值也可以引用解构赋值的其他变量,但前提是这个变量必须已经声明.
let [a = 1,b = a] = [];
console.log(a); //1
console.log(b); //1 模式b使用了变量a,a提前声明了
let [a = 1,b = c] = [];
console.log(a);
console.log(b);
//这里不会有任何打印输出,而是会报错,因为这里的模式b是用了其他变量c来作为默认值,但这个时候c还没有声明,所以就报错了
对象的解构赋值
数组可以解构赋值,对象也可以解构赋值,只是与数组一点不同的是数组的元素是按次序排列的,变量的取值由它所在的位置决定,而对象的属性没有次序,变量必须与属性同名才可以匹配到正确的值.
let {a,b} = {b:12,a:"Nicholas"};
console.log(a);//Nicholas
console.log(b); //12 从demo可以看出,等号左边变量的次序与等号右边同名变量的次数不是必须一一对应,顺序不是一一对应时对于取值没有影响,只要等号两边有同名对应的属性就可以
对象的解构赋值,我们在学习对象的解构赋值的时候,可以先学习一下ES6中的对象的扩展一部分.对象扩展部分之后补充上.