以下内容来自阮一峰老师的ECMAscript入门
1.数组的解构赋值
ES6允许按照一定的模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
let [a,b,c] = [1,2,3];
注意:如果等号的右边是不可遍历的结构,那么将会报错。
只要某种数据结构具有Iterator接口,都可以采用数组形式的结构赋值。
默认值:
结构赋值允许制定默认值,ES6内部使用严格相等的运算符(===),判断一个位置是否有值。如果一个数组的成员不严格等于undefined,默认值是不会生效的。
如果一个默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候才会求值。
默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
let [x = y, y = 1] = [] //ReferenceError x用到默认值y的时候,y还没有声明
2.对象的解构赋值
结构不仅可以用于数组,还可以用于对象。对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;
而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
如果变量名与属性名不一致,必须写成下面这样。
var {foo:baz} = {foo: 'aaa', bar: 'bbb'};//baz 'aaa'
对象的结构赋值是下面形式的简写
let {foo: foo, bar: bar} = {foo: "aaa", bar: "bbb"};
对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者.
与数组一样解构也可用于嵌套结构的对象。
对象的解构也可以指定默认值。
默认值生效的条件是,对象的属性值严格等于undefined.
注意:如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。
let {foo: {bar}} = {baz: "baz"};//报错
上面代码会报错因为结构bar属性时,foo等于undefined,undefined上取子属性就会报错。
let x;
{x} = {x:1} //报语法错误
//正确的写法
let x;
({x} = {x: 1})
js引擎会将{x}理解成一个代码块,从而发生语法错误,只有不将大括号写在行首,避免javaScript将其解释为代码块,才能解决这个问题。
解构赋值允许等号左边的模式中,不放置任何变量名。因此可以写出非常古怪的赋值表达式,虽然毫无意义,但是语法合法。
({} = 'abc');
由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
3.字符串的解构赋值。
字符串也可以解构赋值,这是因为此时,字符串被转换成了一个类似数组的对象。类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
let {length: len} = 'hello'; //len 5
解构赋值的规则是,只要等号右边的值不是对象或数组,就会先将其转化为对象,由于undefined和null无法转化为对象,所以对他们进行解构赋值时会报错。
5.函数参数的解构赋值
function add([x, y]){
return x+y;
}
add([1,2]); //3
函数add的参数表面上是一个数组,但是在传入参数的那一刻,数组参数就被解构成变量x,y。
函数参数的解构也可以使用默认值。
function move({x=0, y=0}){
}
function move({x, y} = {x:0, y:0}){
}
注意上面两者的区别:后者是为move的参数指定默认值,而不是为变量x和y指定默认值。
6.圆括号问题
对于编译器来说一个式子到底是模式还是表达式,没有办法从一开始就知道,必须解析到(或解析不到)等号才能知道。
ES6规定只要有可能导致解构的歧义,就不得使用圆括号。
不能使用圆括号的情况:
1.变量声明语句
2.函数参数(函数参数也属于变量声明,因此不能带有圆括号)
3.赋值语句模式
可以使用圆括号的情况只有一种: 赋值语句的非模式部分,可以使用圆括号
用途:
1.交换变量的值
2.从函数返回多个值
3.函数参数的定义
4.提取JSON数据
5.函数参数的默认值
6.遍历Map结构