两者的区别:一个对象浅复制后,是深层次的对象地址的复制,并没有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会发生改变,而深复制的则是开辟了一个新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
话不多说,上代码:
// 原始对象
var obj = {
a:1,
arr: [2,3],
say:function(){
console.log('hello')
},
obj1:{
arr:[34,55,5],
hand:function(){
console.log('hand')
},
obj3:{
a:1,
take:function(){
console.log('take')
}
}
}
};
// 开始浅复制
var shallowObj = shallowCopy(obj);
// 定义浅复制逻辑
function shallowCopy(src) {
var dst = {};
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
dst[prop] = src[prop];
}
}
return dst;
}
// 改变复制后的新对象属性值(第一层属性)
shallowObj.a = 2;
shallowObj.arr = [9,8];
shallowObj.say = function(){
console.log('world')
}
// 打印新对象的及方法
console.dir(shallowObj)
shallowObj.say(); // world
// 打印原对象及方法
console.dir(obj);
obj.say(); // hello
结果如图所示:
结论 : 修改新对象的属性值,第一层的属性值的确没有变化,重点来了,我们给第二层以及更深层次的属性复制试试
// 原始对象
var obj = {
a:1,
arr: [2,3],
say:function(){
console.log('hello')
},
obj1:{
arr:[34,55,5],
hand:function(){
console.log('hand')
},
obj3:{
a:1,
take:function(){
console.log('take')
}
}
}
};
// 开始浅复制
var shallowObj = shallowCopy(obj);
// 定义浅复制逻辑
function shallowCopy(src) {
var dst = {};
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
dst[prop] = src[prop];
}
}
return dst;
}
// 改变复制后的新对象的属性值(第二层以及更深层次)
shallowObj.obj1.obj3.take = function(){
console.log('shallowObj_take')
}
shallowObj.obj1.hand = function(){
console.log('shallowObj_hand')
}
// 打印新对象的方法调用
shallowObj.obj1.obj3.take(); // shallowObj_take
shallowObj.obj1.hand(); // shallowObj_hand
// 打印原对象的方法调用
obj.obj1.obj3.take(); // shallowObj_take
obj.obj1.hand(); // shallowObj_hand
问题出现了:原对象的方法被新对象的修改,而产生变化。
原因是复制的是对象的地址指针,两个属性共同指向一个对象,只要其一发生变化,另一个也随之变化
深拷贝的方法:
1.可以递归递归去复制所有层级属性
// 原始对象
var obj = {
a:1,
arr: [2,3],
say:function(){
console.log('hello')
},
obj1:{
arr:[34,55,5],
hand:function(){
console.log('hand')
},
obj3:{
a:1,
take:function(){
console.log('take')
}
}
}
};
// 深复制逻辑(递归调用)
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判断obj子元素是否为对象,如果是,递归复制
if(obj[key] && typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
// 开始深复制
var shallowObj = deepClone(obj);
// 改变复制后的新对象的属性值(第二层以及更深层次)
shallowObj.obj1.obj3.take = function(){
console.log('shallowObj_take')
}
shallowObj.obj1.hand = function(){
console.log('shallowObj_hand')
}
shallowObj.obj1.obj3.take(); // shallowObj_take
shallowObj.obj1.hand(); // shallowObj_hand
obj.obj1.obj3.take(); // take
obj.obj1.hand(); // hand
结论:深拷贝后改变对象的属性值,不会影响原始对象的值。
2.除了递归,我们还可以借用JSON对象的parse和stringify
function deepClone(obj){
let _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone
}
let a=[0,1,[2,3],4],
b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
3.除了上面两种方法之外,我们还可以借用JQ的extend方法
$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝
target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。
object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。
let a=[0,1,[2,3],4],
b=$.extend(true,[],a);
a[0]=1;
a[2][0]=1;
console.log(a,b);