核心提示:两者的区别:一个对象浅复制后,是深层次的对象地址的复制,并没有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会发生改变,而深复制的则是开辟了一个新的...
两者的区别:一个对象浅复制后,是深层次的对象地址的复制,并没有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会发生改变,而深复制的则是开辟了一个新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
话不多说,上代码:
// 原始对象 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,则为浅拷贝
targetObject类型 目标对象,其他对象的成员属性将被附加到该对象上。
object1objectN可选。 Object类型 第一个以及第N个被合并的对象。
let a=[0,1,[2,3],4], b=$.extend(true,[],a); a[0]=1; a[2][0]=1; console.log(a,b);