JS Javascript 深拷贝(clone) 操作不会改变原数组的拷贝方式
当我们做的项目中有某种需求是需要复制一份数组的时候我们第一时间会想到的是
let arr = [1, 2, 3, 4, 5]
let arrCopy = arr // [1, 2, 3, 4, 5]
但是这样操作会遇到的一个问题就是“当对arrCopy进行操作(push等)时,原数组arr也会随之改变”
let arr = [1, 2, 3, 4, 5]
let arrCopy = arr // [1, 2, 3, 4, 5]
arrCopy.push(6)
console.log('arrCopy', arrCopy) // arrCopy [1, 2, 3, 4, 5, 6]
console.log('arr', arr) // arr [1, 2, 3, 4, 5, 6]
为了解决这样的问题,就要用到深拷贝(clone)来对数组进行操作。使得复制出一个新数组的同时又使新老数组相互独立。
一、我们可以使用for循环来实现
这种方式实现起来比较简单,也比较容易理解,只是遍历原数组,分别取出原数组内的值添加到新数组中去,就不过多解释了。
let arr = [1, 2, 3, 4, 5]
let arrCopy = []
for (let i = 0; i < arr.length; i++) {
arrCopy.push(numbers[i])
}
arrCopy.push(6)
console.log('arrCopy', arrCopy) // arrCopy [1, 2, 3, 4, 5, 6]
console.log('arr', arr) // arr [1, 2, 3, 4, 5]
二、同理,我们也可以使用forEach来实现
let arr = [1, 2, 3, 4, 5]
let arrCopy = []
arr.forEach((item) => arrCopy.push(item))
arrCopy.push(6)
console.log('arrCopy', arrCopy) // arrCopy [1, 2, 3, 4, 5, 6]
console.log('arr', arr) // arr [1, 2, 3, 4, 5]
三、使用slice()方式来实现
JavaScript中slice() 方法可从已有的数组中返回选定的元素
用法为 array.slice(start, end) // array为一个数组,start为起始索引,end为结束索引。
这样的话我们就可以把起始索引设为0,结束索引设为这个数组的最大长度array.length。就可以得到一模一样的数组了。
let arr = [1, 2, 3, 4, 5]
let arrCopy = numbers.slice(0, numbers.length) // 下方两种方式也一样可以实现效果
// let arrCopy = numbers.slice(0)
// let arrCopy = numbers.slice()
arrCopy.push(6)
console.log('arrCopy', arrCopy) // arrCopy [1, 2, 3, 4, 5, 6]
console.log('arr', arr) // arr [1, 2, 3, 4, 5]
三、使用concat()方式来实现
JavaScript中concat() 方法可以连接两个乃至多个数组,并返回出一个新数组
用法为array.concat(arrayA, arrayB, arrayC) // 这里只写三个,其实可以写更多个。
那如果我concat()中什么也不写,那不就相当于原数组不变并返回一个新数组了么?
let arr = [1, 2, 3, 4, 5]
let arrCopy = arr.concat()
arrCopy.push(6)
console.log('arrCopy', arrCopy) // arrCopy [1, 2, 3, 4, 5, 6]
console.log('arr', arr) // arr [1, 2, 3, 4, 5]
四、使用map()方式来实现
JavaScript中map()方法可以按照原数组顺序依次对元素做处理,类似for循环。
let arr = [1, 2, 3, 4, 5]
let arrCopy = arr.map(item => item)
arrCopy.push(6)
console.log('arrCopy', arrCopy) // arrCopy [1, 2, 3, 4, 5, 6]
console.log('arr', arr) // arr [1, 2, 3, 4, 5]
五、使用Array.from()方式来实现
Array.from()是ES6中新增的一个方法。具有可以把“类数组”对象、“有遍历器接口”的对象转换为数组的功能。
let arr = [1, 2, 3, 4, 5]
let arrCopy = Array.from(arr)
arrCopy.push(6)
console.log('arrCopy', arrCopy) // arrCopy [1, 2, 3, 4, 5, 6]
console.log('arr', arr) // arr [1, 2, 3, 4, 5]
六、使用new Array()方式来实现
JavaScript中new Array()是新建一个数组的功能,里面可以添加多个参数,每个参数都是新数组的元素。
这里呢还要用到就是ES6中的另一个新特性“…”扩展运算符,个人感觉扩展运算符用好了是很方便的。
其实扩展运算符就是将实现了Iterator 接口的对象中的每个元素都一个个的迭代并取出来变成单独的被使用
emmm…在这里呢扩展运算符的主要作用就是依次把原数组中的元素放到new Array()中去当做参数。
let arr = [1, 2, 3, 4, 5]
let arrCopy = new Array(...arr)
arrCopy.push(6)
console.log('arrCopy', arrCopy) // arrCopy [1, 2, 3, 4, 5, 6]
console.log('arr', arr) // arr [1, 2, 3, 4, 5]
七、使用Array.of()方式来实现
Array.of()是ES6中新增的一个方法。具有可以将“一个”或“多个”值转换成数组的功能。
这里的扩展运算符功能与上面的类似,都是依次将元素添加到方法中去当参数。
let arr = [1, 2, 3, 4, 5]
let arrCopy = Array.of(...arr)
arrCopy.push(6)
console.log('arrCopy', arrCopy) // arrCopy [1, 2, 3, 4, 5, 6]
console.log('arr', arr) // arr [1, 2, 3, 4, 5]
八、使用push() + "…"扩展运算符的方式来实现
JavaScript中的push()其实就是向数组后面添加某个参数做该数组的新元素。
上面的for循环+push()可以改为用push(…array)的方式来添加多个元素的功能了。
let arr = [1, 2, 3, 4, 5]
let arrCopy = []
arrCopy.push(...arr)
arrCopy.push(6)
console.log('arrCopy', arrCopy) // arrCopy [1, 2, 3, 4, 5, 6]
console.log('arr', arr) // arr [1, 2, 3, 4, 5]
九、使用unshift() + "…"扩展运算符的方式来实现
既然push()好用,那么unshift()也同样好用。(又水了一条。。。)
JavaScript中的unshift()其实就是向数组前面添加某个参数做该数组的新元素。
let arr = [1, 2, 3, 4, 5]
let arrCopy = []
arrCopy.unshift(...arr)
arrCopy.push(6)
console.log('arrCopy', arrCopy) // arrCopy [1, 2, 3, 4, 5, 6]
console.log('arr', arr) // arr [1, 2, 3, 4, 5]
十、使用Array.reduce()的方式来实现
这种方法不是很常用,不过看一看还是挺有意思的
JavaScript中的Array.reduce()方法会对数组内的数据依次进行操作,并且会返回一个数组。
Array.reduce()方法中有四个参数,Array.reduce((callBackList, thisList, thisIndex, arr) => { return thisItem }, [])
其中callBackList为上一次操作后的返回数据
thisList是本次操作的元素
thisIndex是本次操作的元素索引值
arr是操作的数组(Array)
后面的空[]是默认的重试数据
有兴趣的朋友可以打开debugger看下每次运行时的参数变化就很好理解了。
let arr = [1, 2, 3, 4, 5]
let copy = numbers.reduce((callBackList, thisList, thisIndex, arr) => {
// debugger
callBackList.push(thisList)
return callBackList
}, [])
arrCopy.push(6)
console.log('arrCopy', arrCopy) // arrCopy [1, 2, 3, 4, 5, 6]
console.log('arr', arr) // arr [1, 2, 3, 4, 5]