【ES6】解构赋值的那些事儿

1,107 阅读4分钟

从数组和对象中提取值,赋值给新的变量,称为解构赋值。

一、数组的解构赋值

1.简单格式

以往对a,b,c三个变量赋值的办法

let a = 5;
let b = 3;
let c = 2;

解构赋值

let [a, b, c] = [1, 2, 3];   //三行代码变一行,是不是很爽

2.复杂一点的

let [a, [[b], c]] = [1, [[2], 3]];  //格式要对上

3.变量少,数据多的

let [,,third] = [1, 2, 3];  //顺序要对上,前面可以空出来

4.变量多,数据少的

let [a,b,c] = [1,2];
console.log(a)	//1
console.log(b)	//2
console.log(c)	//undefined

5.默认值-常量

如果后面有值,以后面的为准

let [a,b,c=0] = [1,2,3]
console.log(c)	//3

如果后面的值为undefined,以前面的值为准

let [a,b,c=0] = [1,2,undefined]
console.log(c)	//0

如果后面的值为null,以后面的值为准

let [a,b,c=0] = [1,2,null]
console.log(c)	//null

6.默认值-函数、变量

默认值是函数

function f(){
     console.log('hi');		//会输出
     return 1;
}
let [a=f()] = [];
console.log(a);		//1	

如果后面有值,前面的f()不会被调用,hi不会输出

function f(){
     console.log('hi');		//不会输出
     return 1;
}
let [a=f()] = [10];
console.log(a);		//10	

默认值是变量

let y = 5;
let [x = y] = [];
console.log(x);		//5

二、对象的解构赋值

数组的解构赋值是按照顺序进行赋值的,对象不需要按照顺序,按照key进行赋值

1.简单的

let {b, a} = {
    a: 3,
    b: 4
}
console.log(a,b); 		//3 4

2.复杂一点的

// 一般冒号前是匹配,冒号后才是被赋值的变量
let {b: b, a: a} = {
    a: 3,
    b: 4
}
console.log(a, b);		//3 4

3.更复杂一点的

let obj = {
    p:[
        'Hello',
        {y: 'World'}
    ]
}
let {p,p:[y1,{y:y2}]} = obj;		//匹配p可以重复使用,
console.log(y1,y2);		//Hello,World
console.log(p);

一般拿到定义的时候,需要判断哪些是匹配,哪些是变量。上面的第一个p既是匹配也是变量,第二个p是匹配,y1是变量,y是匹配,y2是变量。

我们看一个匹配可以重复使用的更典型例子:

let obj = {x : 5};
let {x:x1,x:x2,x:x3} = obj;
console.log(x1,x2,x3);		//5 5 5

4.默认值

和数组的情况类似

let {x = 3} = {};
console.log(x);		//3

但是有特例

//数组是正常的
let a;
[a] = [5];
console.log(a);		//可以正常输出a
//对象会出现语法的二义性(无法判断{}是解构赋值还是块作用域)
let a;
{a} = {5};
console.log(a);		//报错:Unexpected token '='

//正确处理需要加个括号
let a;
({a} = {5});
console.log(a);		//5

5.把数组当对象

数组给对象结构赋值有一个好处,可以把数组里的值赋给多个变量,这是在原来纯数组赋值里做不到的。

let array = [1,2,3];
let {0:a1, 0:a2, 1:b, 2:c};
console.log(a1,a2,b,c);		//1 1 2 3

三、字符串的解构赋值

let str = 'abc';
let [a,b,c] = str;
console.log(a,b,c);		//1 2 3

四、包装类的解构赋值

把123(Number)变成123(String)

let {toString : s} = 123;
console.log(5 === Number.prototype.toString());

五、函数参数的解构赋值

使用数组or对象做参数

function join([a, b]){
	return a + b;
}
console.log(join(['Hello', ' World']));	//Hello World

也可以用默认值

//情况1:
function f({a = 0, b = 0} = {}){
    console.log(a, b);
}

f({a: 3, b: 4});	//3 4 (3 4先传给{},再传给a,b)
f({a: 3});		//3 0 (3传给a,b默认用0)
f({});			//0 0 (因为传的是空的,所以用默认值0)
f();			//0 0 (因为没有传,所以用默认值0)

function f2({a, b} = {a: 0, b: 0}){
    console.log(a, b);
}

//情况2:
f2({a: 3, b: 4});	//3 4 (3 4先传给{a: 0, b: 0},再传给a,b)
f2({a: 3});		//3 undefined (3传给{a: 0, b: 0},b默认用undefined)
f2({});			//undefined undefined (因为传的是空的,所以用默认值)
f2();			//0 0 (因为没有传,所以用对象{a: 0, b: 0})

六、解构赋值的常用方法

1.交换两个变量

let [x, y] = [1, 2];
[x, y] = [y, x];
console.log(x,y);	//2 1

2.函数返回一个数组或者对象,需要处理

function f(){
	return [1,2,3];
}
let [x,y,z] = f;
console.log(x,y,z);		//1 2 3

3.给函数传递参数

比如实参数量大于形参时 function f({a, b, c}){ console.log(a, b, c); //undefined 2 3 } f({b: 2, c:3});

4.Json文件的处理

和对象的处理一样

5.给函数的参数设定默认值

和上面函数的解构赋值情况一样

function f({a = 0, b = 0} = {}){
    console.log(a, b);
}

f({a: 3, b: 4});	//3 4 (3 4先传给{},再传给a,b)
f({a: 3});		//3 0 (3传给a,b默认用0)
f({});			//0 0 (因为传的是空的,所以用默认值0)
f();			//0 0 (因为没有传,所以用默认值0)

6.从模块或者API中获得变量或者函数

const {PI, cos, sin} = Math;
console.log(PI,cos,sin);	//3.141592653589793 [function:cos] [function:sin]
console.log(cos(PI/4));		//0.707

比如我们平时引用的模块原理就是这个

const {xxxx, yyyy} = require('moduel-name');