前言
工作中可能会遇到这样一个问题,我明明把数据拷贝了一份,但改变拷贝后的数据居然同时会改变原始数据中的值。那就来看看为什么吧,希望这篇文章可以给你解惑。
什么是浅拷贝?
只拷贝了数据对象的第一层,深层次的数据值与原始数据会互相影响(拷贝后的数据与原始数据还存有关联)
常见浅拷贝的方式: Object.assign()
、 扩展运算符
const obj1 = { name: 'dog', info: { age: 3 } }
const obj2 = Object.assign({}, obj1)
// 或者
const obj2 = { ...obj1 }
obj2.name = 'cat'
obj2.info.age = 4
console.log(obj1) // { name: 'dog', info: { age: 4 } }
console.log(obj2) // { name: 'cat', info: { age: 4 } }
当拷贝后的对象obj2
数据改变的时候会影响原始数据obj1
,因为info
对象拷贝的是源对象指针。
不清楚指针的可以看前面的这篇文章
什么是深拷贝?
不管数据对象有多少层,改变拷贝后的值都不会影响原始数据的值。(拷贝后的数据与原始数据毫无关系)
常见深拷贝的方式:JSON.parse()
和JSON.stringify()
配合使用
const obj1 = { name: 'dog', info: { age: 3 }, fn: function () {} }
const obj2 = JSON.parse(JSON.stringify(obj1))
obj2.name = 'cat'
obj2.info.age = 4
console.log(obj1) // { name: 'dog', info: { age: 3 }, fn: function(){} }
console.log(obj2) // { name: 'cat', info: { age: 4 } }
这种方式有一个弊端,就是无法正确处理函数
和正则
我们也可以手写一个深拷贝的方法(简易基础版)
function deepClone(source) {
// null数据需要特殊处理
if (source === null) {
return source
}
// 校验要拷贝的数据是对象还是数组
const target = Array.isArray(source) ? [] : {}
for (const k in source) {
const val = source[k]
const valueType = typeof val
// 校验拷贝的数据类型
if (valueType === 'function') {
target[k] = new Function(`return ${val.toString()}`)()
} else if (valueType === 'object') {
target[k] = deepClone(val)
} else {
target[k] = val
}
}
return target
}
const obj1 = { name: 'dog', info: { age: 3 }, fn: function () {} }
const obj2 = deepClone(obj1)
obj2.name = 'cat'
obj2.info.age = 4
console.log(obj1) // { name: 'dog', info: { age: 3 }, fn: function(){} }
console.log(obj2) // { name: 'cat', info: { age: 4 }, fn: function(){} }
当然还可以使用第三方库Lodash
中的_.cloneDeep(value)
,强烈推荐这个库,功能非常强大!
关注公众号【麋鹿迷了路】,发送js
获取更多学习资源
喜欢的小伙伴们点个赞吧(〃‘▽’〃) ̄ω ̄= ( ̄▽ ̄)~*