解构赋值
定义:ES6中允许按照一定模式从数组和对象中提取值,然后对变量进行赋值。
1.数组的解构赋值
let [a,b,c] = [1,2,3] //a=1,b=2,c=3
let [ foo,[[bar],baz]]=[1,[[2],3]] // foo =1,bar=2,baz=3
本质上这种写法属于模式匹配,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
如果结构不成功,变量的值就等于Undefined
let [foo] =[]; //foo undefined
let [bar,foo]=[1] //foo undefined
不完全解构:即等号左边的模式只匹配到右边模式的的一部分变量,但结构是可以成功的。
let [x,y]=[1,2,3] //x=1,y=2
let [a,[b],d]=[1,[2,3],4]; a=1,b=2,d=4
如果等号右边的值或是转为对象之后不具备Iterator接口,或不具备Iterator接口那么解构就会报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null
let [foo] ={} //这些解构都会报错
解构赋值允许设置默认值
let [foo=true]=[]; // foo =true
let [x,y='b']=['a']; //x='a' y='b'
2.对象的结构赋值
数组的解构是按次序进行的,变量的取值是由它的位置决定。而对象是没有次序的,变量必须与属性同名才能取得正确的值。
如果变量没有对应的同名属性,则等于undefined。
let {bar,foo} ={foo:"aaa",bar:"bbb"}; //foo="aaa" bar="bbb"
如果变量名与属性名不一致,则必须要写成下面这样:
let {foo:baz}={foo:'aaa',bar:'bbb'}; //baz="aaa";
实际上说明,对象的解构赋值是下面形式的简写
let {foo:foo,bar:bar}={foo:'aa',bar:'bb'}; //foo='aa' bar='bb'
**对象的解构赋值的内部机制:**是先找到同名属性,然后再赋值给对应的变量,真正被赋值的其实是后者,而不是前者
let {foo:baz,bar:bar}={foo:'aa',bar:'bb'};
// baz ='aa'
//foo error:foo is not defined
这说明foo只是匹配模式,不会赋值。真正被赋值的变量是baz
3.字符串的结构赋值
字符串也可以解构赋值,因为字符串被转换成一个类似数组的对象
const [a,b,c]='his';
// a='h' b=i c=s
类似数组的对象都有一个length属性,可以对其进行解构赋值
let {length:len}='hello'; //len=5
4.数值和布尔值的解构赋值
解构赋值时如果等号右边是数值和布尔值,则会先转为对象。
let {toString :s} =123;
s === Number.prototype.toString //true
let {toString :s}=true;
s === Boolean.protype.toString //true
数值和布尔值的包装对象都有toString属性,因此变量S都能取到值。
由于undefined和null无法转为对象,所以对他们进行解构赋值都会报错
let {prop:x} = undefined; //TypeError
let {prop:y} = null; //TypeError