首先,介绍一下相关概念。当我们讨论深浅拷贝的时候,我们针对的是引用类型对象,毕竟对于普通类型,拷贝就是传值,其表现只有深拷贝这种现象。但是对于引用类型来说,对其进行拷贝则可以分为深浅拷贝了。浅拷贝:拷贝前后,不同的引用类型变量引用的是同一块内存,所以这个时候如果源对象的引用类型属性发生了改变的话,那么目标对象也会跟着改变。深拷贝:拷贝前后,不同的引用类型变量引用的不是同一块内存,所以如果源对象中的某个引用类型属性发生了改变的话,那么目标对象并不会跟着改变。标准中常见的浅拷贝方法有:Object.assign(target,
source)。可以举个例子:
- 浅拷贝
var test = {"ffff": "huohuo"}
var obj1 = {
"a": 1,
"childObj": {
"num1": "one",
"num2": "two"
},
test
}
var obj = {}
Object.assign(obj, obj1);
obj1.a = 2;//深浅拷贝,只针对引用类型的对象,像这种情况下,只有深拷贝这一种结果
obj1.childObj.num1 = "three"//对源对象做出改变
obj1.test.ffff = "hehe"//对源对象做出改变
with(obj){
console.log(a)//1
console.log(childObj)//{ num1: 'three', num2: 'two' }
console.log(childObj.num1)//three//和源对象的改变同步,因为对于浅拷贝来说引用的是同一块内存中的对象
console.log(childObj.num2)//two
console.log(test)//{ ffff: "hehe" }
console.log(test.ffff)//"hehe"//和源对象的改变同步,因为对于浅拷贝来说引用的是同一块内存中的对象
}
下面再来看看一个实现了深拷贝的方法:JSON.parse(JSON.stringify())的例子:
var test = {"ffff": "huohuo"}
var obj1 = {
"num": 1,
"childObj": {
"num1": "one",
"num2": "two"
},
test
}
var obj = JSON.parse(JSON.stringify(obj1))
obj1.childObj.num1 = "three"
obj1.test.ffff = "hehe"
console.dir(obj)//并没有跟着发生变化
console.dir(obj1)//源对象发生变化,但是目标对象并没有跟着改变
2.浅拷贝的实现
比如说下面的简单的实现方案,当然就下面这种实现来说还有挺多不足的地方:
function shadowCopy(obj){
if(!obj){throw new Error("it must have parameters")}
var result
for(var key in obj){
result[key] = obj[key]//对于引用类型来说,很显然这样做的话,他们将会引用内存里面的同一块数据
}
return result
}
var test = {"ffff": "huohuo"}
var source = {
"num": 1,
"childObj": {
"num1": "one",
"num2": "two"
},
test
}
var target = shadowCopy(source)
console.dir(target)
source.childObj.num1 = "three"//由于是共享同一块内存,所以目标对象此时发生改变
source.test.ffff = "hehe"//同上
console.dir(target)//根据运行结果来看的确是这样
3.深拷贝的简易实现
下面的这个版本有许多不足,挺多地方没有考虑进去:
function deepCopy(obj){
if(!obj){throw new Error("it must have a parameter")}
var result
for(var key in obj){
if(Object.prototype.toString.call(obj[key]) == "[object Object]"){
result[key] = deepCopy(obj[key])
}else{
result[key] = obj[key]
}
}
return result
}
var test = {"ffff": "huohuo"}
var source = {
"num": 1,
"childObj": {
"num1": "one",
"num2": "two"
},
test
}
var target = deepCopy(source)
console.dir(target)
source.childObj.num1 = "three"
source.test.ffff = "hehe"
console.dir(target)//并没有改变,从这个角度来看,我们对其做到了深拷贝
END