开发中常用的 ES6 新特性 – 解构赋值
let 和 const
由于 var 可以重复声明,而且无法限制修改,也没有块级作用域,在一些时候不是很合适,所以出现了 let 和 const
let:不能重复声明,可以修改,有块级作用域,适合 for 循环等一些场景
const:不能重复声明,有块级作用域,不可以修改,比较适合做全局
变量的结构赋值
数组的解构赋值
let [a,b,c] = [1,2,3]
let [d,[[e],f]] = [1,[[2],3]]//d=1,e=2,f=3
let [x,y,…z] =[‘a’];//x=”a”,y=undefined,z=[] 结构不成功变量的值就为 undefined
不完全解构
let [a,[b],c] = [1,[2,3],4];//a=1,b=2,c=4
对于 set 结构, 可以使用数组的解构数组
let [x,y,z] = new Set([‘a’,’b’,’c’]);//a=a,y=b,z=c
主要数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值,如下斐波那契数列的例子,利用 generator 函数
function* fibs(){
let a = 0 ;
let b = 1;
while(true){
yield a;// 利用 yield 返回中间值
[a,b] = [b,a+b];
}
}
let [first,second,third,fourth,fifth,sixth] = fibs();
//first=0,second=1,third=1,fourth=2,fifth=3,sixth=5
默认值
解构赋值允许指定默认值,es6 内部使用严格相等运算符 === 判断一个位置是否有值,所以只有当一个数组成员严格等于 undefined,默认值才会生效; 默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
let [x,y=’b’] = [‘a’];//x=’a’,y=’b’
let [x=1] = [undefined];//x=1
let [x=1] = [null];//x=null
let [x=1,y=x] = [2];//x=2,y=2 因为先把 2 解构赋给 x,x 把值赋给 y,所以 x,y 都为 2
let [x=1,y=x]=[1,2];//x=1,y=2
对象的解构赋值
数组的解构和对象的解构有一个不同,数组的元素按次序排列,变量的取值由其位置决定;而对象的属性没有次数,变量必需和属性同名,才能取得正确的值。
let {foo:foo,bar:bar} = {foo:’qqq’,bar:’www’}//foo=qqq,bar=www
// 嵌套解构
let obj = {p:[‘hello’,{y:’world’}]};
let {p:[x,{y}]} = obj//x=hello,y=world 此时 p 作为模式不会被赋值
let {p,p:[x,{y}]} = obj//p=[‘hello’,{y:’world’}] 此时 P 作为变量赋值
以下实例进行了三次解构,分别是对 loc,start,line 三个属性,但是最后解构赋值时,只有 line 是属性,start 和 loc 都是模式, 而不是变量
const node = {
loc:{
start:{
line:1,
column:5
}
}
};
// 第一个参数是对 loc 进行解构,得到 loc = {start: { line: 1, column: 5} }
// 第二个参数对 start 进行解构,得到 start = {line: 1, column: 5}
// 第三个参数对 line 进行解构,得到 line = 1
let{loc,loc:{start},loc:{start:{line}}} = node;
console.log(loc);//{start: { line: 1, column: 5} }
console.log(start); //{line: 1, column: 5}
console.log(line);//1
嵌套赋值
let obj = {};
let arr = [];
({foo:obj.prop, bar:arr[0]} = {foo:123,bar:true});
console.log(obj);//{prop:123}
console.log(arr);//[true]
对象的默认值, 和数组的默认值相似
var {x:y=3}={x:5}//y=5
var {x=3} = {x:undefined}//x=3
var {x=3} = {x:null}//x=null
var {foo} = {bar:’bz}//foo=undefined 解构失败变量的值等于 undefined
一些错误写法:
let _tmp = {baz :’bz’};
_tmp.foo.baz;// 报错,因为 foo 已经是 undefined,再取子属性会报错
let x;
{x} = {x:1};// 会报错,因为 JavaScript 引擎会把 {x} 解释成代码块,只有避免将大括号写在行首,避免将其解释成代码块,才能避免报错
let x;
({x} = {x:1});// 正确写法
字符串的解构赋值
const [a,b,c,d,e] = ‘hello’//a=’h’,b=’e’,….
let {length:len}=’hello’//len=5
数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值和布尔值,会先转为对象;而 undefined 和 null 无法转为对象,所以对它们解构赋值会报错
let {toString:s} = 123;
console.log(s === Number.prototype.toString);//true
let {toString:s} = true;
console.log(s === Boolean.prototype.toString);//true
let {prop: x} = undefined; // TypeError
let {prop: y} = null; // TypeError
函数参数的解构赋值
[[1, 2], [3, 4]].map(([a, b]) => a + b);//[3,7]
函数参数的解构可以使用默认值,但是不同的写法会有区别,有如下两种情况,一种是为函数的参数指定默认值,一种是为变量指定默认值
变量的默认值函数 test 的参数是一个对象,通过对对象的解构,得到参数 x,y,解构失败,参数为默认值
function test({x=0,y=0} ={}){
return [x,y];
}
console.log(test({x:2,y:5}));//[2,5]
console.log(test({x:2}));//[2,0]
console.log(test({}));//[0,0]
console.log(test());//[0,0]
函数参数的默认值,下面是为函数的参数指定默认值
function test({x,y} = {x:0,y:0}){
return [x,y];
}
console.log(test({x:2,y:5}));//[2,5]
console.log(test({x:2}));//[2, undefined]
console.log(test({}));//[undefined, undefined]
console.log(test());[0,0]
变量解构赋值的用途
交换变量的值
从函数返回多个值
函数参数的定义
提取 JSON 数据
函数参数的默认值
遍历 Map 结构
输入模块的指定方法