开发中我们经常需要复制一个对象。如果直接用赋值会有下面问题:
一、浅拷贝
首先浅拷贝和深拷贝只针对引用类型
浅拷贝:拷贝的是地址
1.1 常见方法:
① 拷贝对象:Object.assgin() / 展开运算符 {...obj} 拷贝对象
② 拷贝数组:Array.prototype.concat() 或者 [...arr]
const arr = [1, 2, 3]
const a = Array.prototype.concat(arr)
a[1] = 4
console.log(a) // [1, 4, 3]
console.log(arr) // [1, 2, 3]
const arr = [1, 2, 3]
const a = [...arr]
console.log(arr) // [1, 2, 3]
a[1] = 5
console.log(a) // [1, 5, 3]
1.2 浅拷贝的问题
如果是简单数据类型拷贝值,引用数据类型拷贝的是地址 (简单理解: 如果是单层对象,没问题,如果有多层就有问题)
1.3 总结
直接赋值和浅拷贝有什么区别?
直接赋值的方法,只要是对象,都会相互影响,因为是直接拷贝对象栈里面的地址
浅拷贝如果是一层对象,不相互影响,如果出现多层对象拷贝还会相互影响
浅拷贝怎么理解?
拷贝对象之后,里面的属性值是简单数据类型直接拷贝值
如果属性值是引用数据类型则拷贝的是地址
二、 深拷贝
首先浅拷贝和深拷贝只针对引用类型
深拷贝:拷贝的是对象,不是地址
常见方法:
通过递归实现深拷贝
lodash/cloneDeep
通过JSON.stringify()实现
2.1 通过递归实现深拷贝
① 函数递归
如果一个函数在内部可以调用其本身,那么这个函数就是递归函数
简单理解:函数内部自己调用自己,这个函数就是递归函数
递归函数的作用和循环效果类似
由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件 return
② 利用递归函数实现 setTimeout 模拟 setInterval效果
需求:
页面每隔一秒输出当前的时间
输出当前时间可以使用:new Date().toLocaleString()
间歇函数:每间隔一段时间执行多次的函数
setInterval(function() {
document.querySelector('div').innerHTML = new Date().toLocaleString()
}, 1000)
延时函数:延时一段时间只执行一次的函数
③ 通过递归函数实现深拷贝
2.2 js库lodash里面cloneDeep内部实现了深拷贝
<script src="./lodash.min.js"></script>