JS中的扩展运算符一般用于以下情况:
- 数组和对象的深拷贝(仅限单层数组或对象的深拷贝,实际上对于数组和对象的嵌套来说还是浅拷贝)
let arr = ['a', 'b']
let arr1 = [...arr]
let [...arr2] = arr
console.log(arr1, arr2) //输出['a', 'b'] ['a', 'b']
这里数组arr和arr1和arr2存储在不同的对内存地址中,互相之间不会产生任何影响。
- 数组或对象的拼接
let arr = ['a', 'b']
let arr1 = ['c']
let arr2 = [...arr, ...arr1]
console.log(arr2) //输出 ["a", "b", "c"]
这里要注意的是:如果是对象的拼接,对于同一个key的键值对,后面的会覆盖前面的,如:
let obj1 = {name: 'xyp', age: 18}
let obj2 = {name: 'zyp'}
let obj3 = {...obj1, ...obj2}
console.log(obj3) //输出结果为:{name: "zyp", age: 18}
- 函数传参(解构赋值)
function add(...arr) {
let sum = 0
arr[0] = 11
sum = arr.reduce((prev, cur) => {
return prev + cur
}, 0)
return sum
}
let arr = [1, 2]
let sum = add(...arr)
console.log(sum) //得到的值是13
console.log(arr) //得到的值依然是[1,2]
我们知道,js中函数参数的传递时按值传递的,详见我的另一篇文章
那么这里的传参就不是简单的赋值操作了,而是在堆内存中重新开辟了一块空间来存放传入的数组,再将该块内存中的地址传递给参数arr,其实这里也就是深拷贝的意思。此时你对arr再做任何操作也影响不到外层的arr了。
在ES5中通过apply函数和bind+call函数也可以实现上述深拷贝传参。
- apply方式
let arr = [1,2]
function add(x, y) {
x= 5
let sum = 0
sum = x + y
return sum
}
let sum= add.apply(add, arr)
console.log(sum) // 输出7
console.log(arr) //输出 [1, 2]
- bind + call 方式
let sum2 = add.bind(add,1,2).call()
console.log(sum2) //输出7
当然,由于扩展运算符在传参时可以对参数进行结构赋值,所以以上bind+call方法在传参时可以改成如下:
let sum2 = add.bind(add, ...arr).call()
console.log(sum2) //输出7
因此对于传参时的结构赋值来说,我的理解是对部署了Symbol.iterator接口的数据类型进行解构。
可以将字符串解构成数组,将数组解构成’用逗号分隔的参数序列’
小技巧:
- 数组的push操作再也不用用循环啦
let arr1 = ['a', 'b']
let arr2 = ['c']
arr1.push(...arr2)
- 求取数组中的最大(小)值也可以直接使用Math.max啦
let arr = [1,2,3,4]
let max = Math.max(...arr)
- 将字符串转化成数组也很easy啦,不用借助match函数了。
let str = 'abcde'
let arr = [...str]
以前用match函数的实现:
let arr = str.match(/\w/g)
- 同时将其他部署了Symbol.iterator接口的对象转化成数组也更方便啦
var nodeList = document.querySelectorAll('div');
var array = [...nodeList];