要理解和实现js中的浅拷贝和深拷贝,不妨先来看一下js中基本数据类型和引用数据类型的区别:
基本数据类型保存在栈内存中,引用数据类型保存在堆内存中,然后在栈内存中保存了一个对堆内存中实际对象的引用,即数据在堆内存中的地址,JS对引用数据类型的操作都是操作对象的引用而不是实际的对象,如果obj1拷贝了obj2,那么这两个引用数据类型就指向了同一个堆内存对象,具体操作是obj1将栈内存的引用地址复制了一份给obj2,因而它们共同指向了同一个堆内存里面的对象。
什么是浅拷贝和深拷贝?
浅拷贝只是拷贝了一层,更深层次的对象级别只是拷贝了引用,也就是拷贝前的对象和拷贝后的对象在堆内存中是同一个对象。而深拷贝是拷贝多层,也就是每一层的数据都会进行拷贝。接下来就用原生js来实现浅拷贝和深拷贝。
浅拷贝的实现:
let oldObj = {
name:'zhangsan',
age: 18,
sex: `男`,
}
let newObj = {};
for(let val in oldObj){
//val是属性名,oldObj是属性值
newObj[val] = oldObj[val]
}
console.log(newObj);
执行代码控制台输出
{ name: 'zhangsan', age: 18, sex: '男' }
除了这种方法,ES6还提供了Object.assign()来实现浅拷贝
Object.assign(newObj,oldObj)
上面的oldObj中只包含了简单数据类型,当包含引用数据类型时就不能简单的通过浅拷贝来实现了。
深拷贝:
let oldObj = {
name:'zhangsan',
age: 18,
sex: `男`,
msg: {
name:`lisi`,
age:20,
sex:'女',
},
aihao: ['打篮球','跳舞',`唱歌`],
};
let o = {}
let deepCopy = (newObj,oldObj)=>{
for(let k in oldObj) {
//获取属性值
let item = oldObj[k]
//判断这个值是否为数组
if(item instanceof Array) {
newObj[k] = []
deepCopy(newObj[k],item)
}else if(item instanceof Object) {
//判断这个值是否为对象
newObj[k] = {}
deepCopy(newObj[k],item)
}else {
//属于简单数据类型,直接赋值
newObj[k] = item
}
}
}
deepCopy(o,oldObj)
console.log(o);
通过上面的代码,控制台输出拷贝成功的对象o:
{
name: 'zhangsan',
age: 18,
sex: '男',
msg: { name: 'lisi', age: 20, sex: '女' },
aihao: [ '打篮球', '跳舞', '唱歌' ]
}