Fork me on GitHub

解构赋值

一开始用的解构赋值很简单,后来学习了一些react基础,发现里面应用了大量的解构赋值,由于个人一直理解的都很肤浅,所以决定整理学习一下。

下面的内容主要针对什么是解构赋值和解构赋值的语法规则来进行介绍,并提出了解构赋值在不同数据类型中的用法。

什么是解构赋值

ES6允许按照一定的模式,从数组和对象中提取,并对变量进行赋值。

基本用法

大概最常用的几种用法如下:
(1)声明多个变量时

1
2
3
let a = 1,
b = 2,
c = 3;

这里的let声明可以简单理解为var,上面的代码应用解构赋值可以改为:

1
let [a, b, c] = [1, 2, 3];

(2)解构赋值就是左右两边的模式匹配(对应的位置找对应的值)

1
let [one, [two, [three]]] = [1, [2, [3]]];

运行结果
他允许某个值不传入:

1
let [a, b, c] = [1, , 2];

运行结果
允许传入多个值(不完全解构,右边的值多):

1
2
3
4
let [a, b, c] = [1, 2, 3, 4];
a //1
b //2
c //3

允许某个变量对应多个值(rest运算符):

1
let [a, b, ...c] = [1, 2, 3, 4, 5, 6];

运行结果
此时rest运算符(…)只能放在最后一个元素(c),如果前面元素用会报错,查看报错信息提醒如下:
运行结果
(3)默认解构赋值
当右边的值严格等于(====)undefined时,将左边默认的值赋值给变量。否则,将右边的值赋给变量

1
var [a, b, c] = [];

取出右边数组的每一项并没有值,为undefined,按照默认解构赋值,左边数组并没有定义具体的值,所以均为undefined
运行结果

1
let [x = 1, y = 2, j = 3] = [8];

右边的数组中只有一项,对应左边的第一项x,左边另外两项并没有被赋予值,等于undefined,进行默认解构赋值
运行结果

1
let [x = 1, y = 2, j = 3] = [null, 2, 4];

只有右边严格等于undefined,才执行默认的解构赋值。undefined == null,并不是绝对等于。
运行结果

(4)当右边的值不是可以循环的解构时,下面的情况会报错

1
var [a, b, c] = 1;

报错信息提示如下:
运行结果
1(数字类型)并不是可以遍历的iterable接口,所以对于右边的值不可遍历的其他类型的值也会报错。

1
2
3
4
5
var [a, b, c] = false;          //布尔值
var [a, b, c] = undefined; //undefined
var [a, b, c] = NaN; //NaN
var [a, b, c] = null; //null
var [a, b, c] = {}; //左边数组,右边对象,不匹配

(5)当左边含有需要解构的变量时,需要根据不同变量声明的方式(var let const)进行考虑

1
2
3
var [a = b, b = 2] = [];
a //undefined
b //2

根据var声明变量存在变量声明提升的特点,上面的代码等同于下面的形式:

1
2
3
4
var a;
var b;
a = b; //此时a,b刚声明没有赋初值均为undefined
b = 2;

如果换一种变量声明的方式,上面的代码就会报错,如下:

1
let [a = b, b = 2] = [];

报错信息提示如下:
运行结果
根据let变量声明的特点,没有变量声明提升,变量只能在声明以后才会存在。所以上述代码可以修改如下:

1
2
3
let [a = 2, b = a] = [];
a //2
b //2

对象的解构赋值

(1)对象由属性名和属性值组成,通常情况都是根据对象的属性名查找对应的属性值。

1
let {a, b, c} = {a: 1, b: 2, c: 3};

左边和右边进行匹配,查找对应项的值。
运行结果

(2)在赋值号左边也可以将属性值用变量进行占位,模式匹配时,相应的属性名对应属性名,属性值对应属性值。

1
let {bar: baz} = {bar: 3};

运行结果

(3)指定默认值时:

1
var {x, y = 5} = {x: 1};

运行结果
(4)对象和数组可以混合使用

1
var {name: n, age: [a, b, c]} = {name: 'fs', age: [10, 15, 20]};

运行结果

字符串的解构赋值

字符串会转化成一个类数组的对象,类数组含有length属性

1
let [a, b, c, d, e] = 'hello';

运行结果
属性名不是变量:

1
2
let {length} = 'fsm';
length //3

函数的解构赋值

函数调用时,对应的实参和形参进行解构赋值。

1
2
3
4
5
function add([x, y]){
return x + y;
}

console.log(add([1, 2])); // 3

当用不同的形式调用函数执行时,主要看实参是否传入,是以何种形式传入

1
2
3
4
5
6
7
function move({x = 0, y = 0} = {}) {
console.log([x, y]);
}
move({x: 3, y: 8}); //[3, 8]
move({x: 3}); //[3, 0]
move({}); //[0, 0]
move(); //[0, 0]

传入参数时,看参数是否严格等于undefined。没有传入参数时,函数正常执行,根据原来的形式进行解构

1
2
3
4
5
6
7
function deal({x, y} = {x: 0, y: 0}) {
console.log([x, y]);
}
deal({x: 3, y: 8}); //[3, 8]
deal({x: 3}); //[3, undefined]
deal({}); //[undefined, undefined]
deal(); //[0, 0]

具体的用法可以查看阮一峰老师的博客点击这里