ES6 -- 2.解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。

一、数组的解构赋值

//以前为变量赋值,只能直接指定值
let a=1;
let b=2;
let c=3;

//ES6 允许写成下面这样
let [a,b,c] = [1,2,3];
//上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值

本质上,这种写法属于‘模式匹配’,只要等号两边的模式相同,左边的变量就会被赋予对应的值,下面我们用例子来深入了解它:

let [foo,[[bar],baz]] = [1,[[2],3]];
foo //1
bar //2
baz //3

let [, , third] = ["foo", "bar", "baz"];
third  //"baz"

let [x, , y] = [1,2,3]
x  //1
y  //3

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []

如果解构不成功,变量的值就等于undefined

let [foo] = [];
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

如果等号的右边不是数组(或者说不可便遍历的解构),那么将会报错。

let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
//xxx is not iterable

解构赋值允许指定默认值

let [foo=true] = [];
foo;   //true

let [x,y = 'b'] = ['a'];
x  //'a'
y  //'b'

let [x,y = 'b'] = ['a',undefined];
x  //'a'
y  //'b'
!:ES6内部使用严格相等运算符(===),所以只有当一个值严格等于undefined,默认值才会生效
let [x = 1] = [undefined]
x //1
let [x = 1] = [null]
x  //null

如果默认值是一个表达式,这个表达式是惰性求值的,即只有在用到的时候,才会求值。

function f(){
	console.log('aaa')
	return 'aaa'
}
let [x = f()] = [1]
//这里的代码,x能取到值1,所以函数f()不会执行

let [x = f()] = [undefined]
//这里的代码,x取不到值,所以函数f()会执行

默认值可以引用解构赋值的其他变量,但该变量必须已经声明。

let [x=1,y=x]=[];
x  //1
y  //1

let [x=1,y=x] = [2]
x  //2
y  //2

let [x=1,y=x] = [1,2]
x  //1
y  //2

let [x=y,y=1]=[];
//y is not defined

二、对象的解构赋值

let {bar,foo}={foo:'aaa',bar:'bbb'};
foo  //'aaa'
bar  //'bbb'

let {baz}={foo:'aaa',bar:'bbb'};
baz  //undefined

对象的解构赋值,可以很方便地将现有对象的方法赋值到某个变量。

let {sin,cos,tan} = Math;
const {log} = console;
log('hello')  //hellos

如果变量名与属性名不一致,必须写成下面这样。

let {foo:baz} = {foo:'aaa',bar:'bbb'};
baz  //'aaa'
foo  //foo is undefined

let obj={first:'hello',last:'world'};
let {first:f,last:l} = obj;
f  //'hello'
l  //'world'

这实际上说明,对象的解构赋值是下面形式的简写:
let {foo:foo,bar:bar} = { foo:'aaa',bar:'bbb' }

与数组一样,解构也可以用于嵌套结构的对象。

let obj = {
	p:[
		'Hello',
		{y:'World'}
	]
}
let {p,p:[x,{y}]} = obj;
p   //['Hello',{y:'World'}]
x   //'Hello'
y   //'World'

const node = {
	loc:{
		start:{
			line:1,
			column:5
		}
	}
}
let {loc,loc:{start},loc:{start:{line}}} = node;
line //1
start  //{line:1,column:5}
loc    //{start:{line:1,column:5}}

下面是嵌套赋值的例子:

let obj = {};
let arr = [];
{foo:obj.prop,bar:arr[0]} = {foo:123,bar:true}
obj  //{prop:123}
arr  //[true]		

对象的解构也可以指定默认值
var {x=3} = {};
x  //3
var {x,y=5} = {x:1};
x  //1
y  //5

var {x:y=3}={};
y  //3
var {x:y=3} = {x:5}
y  //5
var { message:msg='Something went wrong'} = {}
msg  //Something went wrong

默认值生效的条件是,对象的属性值严格等于undefined

var {x=3}={x:undefined};
x  //3
var {x=3}={x:null}
x  //null

由于数组本质是特殊的对象,因此可以对数组进行对象属性的结构

let arr = [1,2,3]
let {0:first,[arr.length-1]:last} = arr
first   //1
last    //3

三、字符串的解构赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。

const [a,b,c,d,e] = 'hello';
a  //'h'
b  //'e'
c  //'l'
d  //'l'
e  //'o'
let {length:len} = 'hello'
len  //5

数值和布尔值的解构赋值

let {toString:a} = 123
a // f toString(){}
//123会先被转为Number对象
a ==== Number.prototype.toString //true


let {toString:s} = true
s // f toString(){}
//true会先被转为Boolean对象
s === Boolean.prototype.toString 

四、解构的用途
1.交换变量的值

let x=1;
let y=2;
[x,y]=[y,x];
x  //2
y  //1

2.从函数返回多个值
函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回,有了解构赋值,取出这些值就非常方便。

function example(){
	return [1,2,3]
}
let [a,b,c] = example();

function example(){
	return {
		foo:1,
		bar:2
	}
}
let {foo,bar} = example();

3.函数参数的定义
解构赋值可以方便地将一组参数与变量名对应起来。

参数是一组有次序的值
function f ( [ x,y,z ]) { ... }
f([1,2,3]);

参数是一组无次序的值
function f({x,y,z}){ ... }
f({z:3,y:2,x:1})

4.提取JSON数据

let jsonData = {
	id:42,
	status:"OK",
	data:[867,5309]
}
let {id, status, data:number} = jsonData;
console.log(id, status, number);
42,'OK',[867,5309]

5.函数参数的默认值

jQuery.ajax = function(url,{
	async = true,
	beforeSend = function(){},
	cache = true,
	complete = function(){},
	crossDomain = false,
	global = true,
	// ...more config
}={}){
	// ...do stuff
}

6.遍历Map结构

const map = new Map();
map.set('first','hello');
map.set('second','world');
for(let [key,value] of map){
	console.log(key + 'is' + value);
}
//first is hello
//second is world

如果只想获取键名,或者只想获取键值,可以写成:

```javascript
for(let [key] of map){
	//获取键名
}

for(let [,value] of map){
	//获取键值
}

7.输入模块的制定方法

const {SourceMapConsumer,SourceNode} = require('source-map');
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值