从数组和对象中提取值,赋值给新的变量,称为解构赋值。
一、数组的解构赋值
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');