ES6解构赋值
一、解构赋值是什么
ES6允许按照一定模式从数组和对象中提取值,然后对变量进行赋值,这被称为解构
二 为什么使用解构赋值
根本上是为了获取对象或者数组内的数据更加方便。
三、解构赋值的分类
1.数组的解构赋值
eg:
let [a,b,c] = [1,2,3];
这种写法本质上属于模式匹配,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
不完全解构:等号左边的模式只匹配一部分的等号右边的数组。如果等号的右边不是数组,或者严格来说不是可遍历的结构,那么将会报错。
let [foo] = 1;
只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值。
默认值:
结构赋值允许指定默认值。
let [foo = true] = [];
foo //true
let [x,y='b'] = ['a'];//x='a',y='b'
let [x,y='b'] = ['a',undefined0000];//x='a',y='b'
ES6使用严格相等判断数组的某个位置是否有值,所以,一个数组成员必须严格等于undefined,默认值才会生效。
let [x = 1] =[undefined] //x=1
let [x = 1] =[null] //x=null
默认值还可以引用解构赋值的其他变量,但该变量必须已经声明。
let [x = 1,y = x] = []; //x=1;y=1
let [x = 1, y = x] = [2]; //x=2;y=2
可以跳过元素获取:
let [a, ,c] = [1,2,3]; //a=1,c=3
可以获取剩余元素:
let [a,b, …c] = [1,2,3,4,5]; //a=1,b=2,c=[3,4,5]
2.对象的解构赋值
对象的结构赋值与数组的结构赋值最大的不同是,数组的元素是按次序排列的,变量的取值是由它的位置决定的;而对象的属性没有次序,变量必须与属性同名才能取到正确的值。
(1)变量名与属性名不一致的写法:
let {foo:baz} = {foo:'hello', bar:'world'} //baz = 'hello'
说明对象的解构赋值是下面形式的简写:
let {foo:foo} = {foo:'hello', bar:'world'} //foo = 'hello'
所以对象结构赋值的内部机制是:先找到对象内同名属性,然后再赋值给对应的变量 。真正被赋值的是后者baz,foo是匹配模式。
(2)对嵌套结构的对象进行解构:
let obj = {
p: [‘aaa’ , {y: ’ bbb’ }]
}`
let { p : [x , {y}]} = obj ; //此处p为匹配模式,不会被赋值,x、y为变量。x=‘aaa’,y=‘bbb’
若想p也被赋值:
let { p , p : [x , {y}]} = obj ;
(3)对象的解构也可以指定默认值,生效条件是 ,属性值必须严格等于undefined。
(4)将一个已经声明的变量用于解构赋值:
错误写法:下面的代码会报错,因为JS引擎会将 {x} 理解为代码块,从而发生语法错误。想解决这个问题,只有不将大括号写在行首。
let x;
{x} = {x:1};
正确写法:
let x;
( {x} = {x : 1}) ;
(5)对象的解构赋值可以方便的将对象的方法赋值到某个变量。
let {log, sin, cos} = Math;
这样使用起来会方便很多。
(6)数组是特殊的对象,可以对其进行属性解构
let arr = [1,2,3];
let {0: first, arr[arr.length-1]:last}= arr; // first:1;last:3
arr的0键对应值为1,键对应值是3.
3.字符串的解构赋值
字符串能够解构赋值是因为被转换成了一个类似数组的对象。
const [a,b, c] = 'hello';
类似数组的对象都有length属性,还可以对这个属性进行解构赋值:
let {length: len} = 'hello';// len = 5
4.数值和布尔值的解构赋值
解构时,首先会将数值和布尔值转换为对象。 可以对数值和布尔值的包装对象进行赋值。
let {toString :s} = 123
s === Number.prototype.toString;// true
注意:解构赋值的规则是,只要等号右边不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值时会报错。
5.函数参数的解构赋值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
]
上面代码,为x、y指定默认值.
上述参数解析失败,x和y等于默认值。
下面这种写法,会得到不一样的结果:
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
]
上面的代码是为move函数的参数指定默认值,而不是为x 、y指定默认值,所以结果会不一样。
四、解构赋值的应用
(1)交换变量的值
lwt x =1, y = 2
[x , y] = [y , x];
(2)从函数返回多个值
函数只能返回一个值,如果要返回多个值,只能使用数组或对象,有了解构赋值,取出这些值就非常方便。
(3)函数参数的定义
解构赋值可以方便地将一组参数和变量对应起来。
参数是一组无序的值:
function f([x, y ,z]){......}
f([1, 2, 3]);
参数是一组无次序的值
function f({x,y,z}){......};
f({z:344, y:2, x:1});
(4)提取JSON数据
let jsonData = {
id:42,
status:‘ok’
}
let {id , status} = jsonData;
(5)函数参数的默认值
function = (url, { async = true, status: ‘ok’}) { …}
指定参数的默认值,这样就避免了在函数内部再写 var async = config.async || true;
(6) 遍历Map解构
任何部署了Iterator接口的对象都可以用for…of循环遍历、 Map解构原生支持Iterator接口,配合变量的解构赋值,非常方便。
var map =new Map();
map.set( ‘first’, ‘hello’);
map.set( ‘second’ , ‘world’);
for([key,value] of map){
console.log(key + 'is ’ +value);
}
注意,获取value时的写法,不加逗号得到的还是key
for( [ , value] of map){
console.log(value);
}
(7)输入模块的指定方法
加载模块时,往往需要指定输入的方法。解构赋值使得输入语句非常清晰。
const {SourceNode} = require("source-map");