开发中经常需要复制一个对象。如果直接用赋值会有下面问题:
首先浅拷贝和深拷贝只针对引用类型
浅拷贝
浅拷贝:拷贝的是地址
常见方法:
-
拷贝对象:
Object.assgin()/ 展开运算符{...obj}拷贝对象 -
拷贝数组:
Array.prototype.concat()或者[...arr]
// 展开运算符
const o = { ...obj }
o.age = 20
console.log(o) // {uname: 'pink', age: 20}
console.log(obj) // {uname: 'pink', age: 18}
// Object.assign
const o = {}
Object.assign(o, obj)
o.age = 20
console.log(o) // {uname: 'pink', age: 20}
console.log(obj) // {uname: 'pink', age: 18}
如果是简单数据类型拷贝值,引用数据类型拷贝的是地址 (简单理解: 如果是单层对象,没问题,如果有多层就有问题)
深拷贝
深拷贝:拷贝的是对象,不是地址
常见方法:
-
通过递归实现深拷贝
-
lodash/cloneDeep
-
通过JSON.stringify()实现
通过递归实现深拷贝
函数递归:
如果一个函数在内部可以调用其本身,那么这个函数就是递归函数
简单理解:函数内部自己调用自己, 这个函数就是递归函数
递归函数的作用和循环效果类似
由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件 return
let i = 1
function fn() {
console.log(`这是第${i}次`)
if (i >= 6) {
return
}
i++
fn()
}
fn()
通过递归函数实现深拷贝(简版)
const obj = {
uname: 'pink',
age: 18,
hobby: ['乒乓球', '足球'],
family: {
baby: '小pink'
}
}
const o = {}
// 深拷贝(简版)
function deepCopy (newObj, oldObj) {
for (const key in oldObj) {
if (oldObj[key] instanceof Array) {
newObj[key] = []
deepCopy(newObj[key], oldObj[key])
} else if (oldObj[key] instanceof Object) {
newObj[key] = {}
deepCopy(newObj[key], oldObj[key])
} else {
newObj[key] = oldObj[key]
}
}
}
deepCopy(o, obj)
console.log(o)
console.log(obj)
js库lodash里面cloneDeep内部实现了深拷贝
<script src="./lodash.min.js"></script>
<script>
const obj = {
uname: 'pink',
age: 18,
hobby: ['乒乓球', '足球'],
family: {
baby: '小pink'
}
}
const o = _.cloneDeep(obj)
console.log(o)
o.family.baby = '老pink'
console.log(obj)
通过JSON.stringify()实现
const obj = {
uname: 'pink',
age: 18,
hobby: ['乒乓球', '足球'],
family: {
baby: '小pink'
}
}
// 把对象转换为 JSON 字符串
// console.log(JSON.stringify(obj))
const o = JSON.parse(JSON.stringify(obj))
console.log(o)
o.family.baby = '123'
console.log(obj)