很多方法会接受不固定数量的参数,例如Math.max(),有时候我们会希望能以数组的元素作为参数来动态传递数量的参数。
数组和参数列表很像,他们是否可以相互转换呢?
使用ES6的扩展运算符...可以完美达到这一点
利用扩展运算符
Math.max(1, 2, 3) //3
arr = [1, 2, 3]
Math.max(...arr) //3
-
扩展运算符是操作列表数据(数组和对象以及参数)非常有用的运算符
-
善用扩展运算符,让列表数据的赋值更加动态和清晰
扩展运算符的概念
扩展运算符是ES6标准,属于解构赋值的内容之一。
为了方便讲解,我们引入新的概念:列表
列表不是一种数据类型,甚至不是标准的名称,而是仅仅在本文中用于解释扩展运算符...的概念名词
扩展运算符可以用于在数组和列表间的转换,但是最终只能用数组的形式展现,因为列表不是数据类型,而是包含数据的排列表
列表最典型的体现就是函数参数,
arr = [1, 2, 3] //数组
function fo(a, b, c){
console.log(arguments)
}
fo(1, 2, 3) //参数列表 //[1, 2, 3]
fo(...arr) //扩展运算符//[1, 2, 3]
arguments 包含所有实参的数组
当在数组前使用扩展运算符时,数组将被解构,并释放一个包含其元素的列表。
可以看作fo(...[1, 2, 3])等同于fo(1, 2, 3)
当然也可以将列表转换为数组形式,以便调用它的元素,当在本该接收列表的地方使用扩展运算符接收将把列表内容变成数组并赋值给变量。可以看作function(...a){ a }等同于function(){ arguments }
理解扩展运算符。
如果发生理解困难,可以把扩展运算符看成增删中括号的过程
理解数组转列表的过程
当扩展运算符被用于本该输入列表的引用操作时,比如在函数实参列表中。
arr = [1, 2, 3] //数组
function fo(a, b, c){
console.log(arguments)
}
fo(...arr)
还是这个熟悉的例子,我们把数组变量直接写在fo()函数中
fo(...[1, 2, 3]
然后去掉方括号和扩展运算符
fo(1, 2, 3)
以上三个调用fo()方法的输出完全一致
那么如何理解列表转数组的过程呢
与数组转列表不同,因为列表不是数据类型,因此在列表转数组时扩展运算符后的变量实际上是用来储存转换后的数组用的,但是要把扩展运算放在本该输出列表的赋值操作内。比如在函数形参列表中。
function fo(...a){
console.log(a)
}
fo(1, 2, 3)
在本例中,函数声明处的小括号内是原来放入变量接收实参的,但我们使用了扩展运算符来接收实参 我们把实参外包裹中括号然后去掉形参的扩展运算符
function fo(a){
console.log(a)
}
fo([1, 2, 3])
上面两种方法的输出完成一致
更多复杂的实例
合并数组、对象
a = [3, 4]
b = [1, 2, ...a]
这明显是一个数组转列表的操作 同样去掉方括号和扩展运算符即可
a = [3, 4]
b = [1, 2, ...[3, 4]]
c = [1, 2, 3, 4] //b与c完全相同
它让合并数组更加便捷和清晰
obj1 = {b: 2, c: 3}
obj2 = {a: 1,...obj1}
对象的扩展运算与数组类似
obj1 = {b: 2, c: 3}
obj2 = {a: 1,...{b: 2, c: 3}}
obj3 = {a: 1, b: 2, c: 3} //obj2与obj3完全相同
拆分数组、对象
能合并自然能拆分
let arr1
let arr2
[arr1,...arr2] = [1, 2, 3]
这涉及到结构赋值,因为扩展运算符本来就是解构赋值的内容,这里不详细展开。 以上代码可以这样来解析
let arr1
let arr2
arr1 = 1
arr2 = [2, 3]
赋值与引用
JavaScript中有大量的赋值与引用操作,他们决定着扩展运算符起到的作用
let arr1 = [3, 4]
let arr2, arr3
[arr3, ...arr2] = [1, 2, ...arr1]
- 为了方便讲解,在本文中我们把等号左边的表达式称之为赋值表达式,等号右边的表达式称之为引用表达式,在两种表达式中使用扩展运算符的意义不同。
- 在赋值表达式中,扩展运算符表示把列表转为数组,运算符后跟需要将结果赋值的变量;而在引用表达式中,扩展运算符表示把数组转为列表,运算符后跟需要转为列表的数组。
- 为了方便解析赋值运算的过程,我们通常先看引用表达式,然后再看赋值表达式。
我再来看一遍下面的例子
let arr1 = [3, 4]
let arr2, arr3
[arr3, ...arr2] = [1, 2, ...arr1]
等号左边的内容是引用表达式,按#理解数组转列表的过程#中表述的解析即可
let arr1 = [3, 4]
let arr2, arr3
[arr3, ...arr2] = [1, 2, 3, 4]
等号左边为赋值表达式,按解构赋值的理解来得到下面的内容
let arr1 = [3, 4]
let arr2, arr3
arr3 = 1
[...arr2] = [2, 3, 4]
然后按照#理解列表转数组的过程#的描述,其实是相当于把2, 3, 4这个列表转换为数组并赋值给arr2,方括号仅仅是一个容器,用于解构。
得到
let arr1 = [3, 4]
let arr2, arr3
[arr3, ...arr2] = [1, 2, ...arr1]
//等同于
arr3 = 1
arr2 = [2, 3, 4]
由于扩展运算是解构赋值的分支,你可能得先了解解构赋值的内容,博主日后有空也会出一篇解构赋值的专题。以下是推荐的几个关于解构赋值的官方中文文档。 ES6标准文档-解构赋值中文文档(推荐) MDN Web Docs解构赋值中文文档