深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。
假设B复制了A,修改A的时候,看B是否发生变化:
如果B跟着也变了,说明是浅拷贝,拿人手短!(修改堆内存中的同一个值)
如果B没有改变,说明是深拷贝,自食其力!(修改堆内存中的不同的值)
浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,
深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,
使用深拷贝的情况下,释放内存的时候不会因为出现浅拷贝时释放同一个内存的错误。
浅复制:仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。
深复制:在计算机中开辟一块新的内存地址用于存放复制的对象。
浅拷贝实例:
//此递归方法不包含数组对象 var obj = { a:1, arr: [2,3] }; var shallowObj = shallowCopy(obj); function shallowCopy(src) { var newobj = {}; for (var prop in src) { if (src.hasOwnProperty(prop)) { newobj[prop] = src[prop]; } } return newobj; }
因为浅复制只会将对象的各个属性进行复制,并不会进行递归复制,而JavaScript存储对象是存地址的,所以浅复制会导致Obj.arr和shallowObj.arr指向同一块内存地址:
导致的结果就是:
shallowObj.arr[1] = 5; console.log(obj.arr[1]); //5
深拷贝实例:
var obj = { a:1, arr: [1,2], nation : '中国', birthplaces:['北京','上海','广州'] }; var obj2 = {name:'杨'}; obj2 = deepCopy(obj,obj2); console.log(obj2); //深复制,要想达到深复制就需要用递归 function deepCopy(o, c){ var c = c || {}; for(var i in o){ if(typeof o[i] === 'object'){ if(o[i].constructor === Array){ //这是数组 c[i] = []; }else{ //这是对象 c[i] = {}; } deepCopy(o[i], c[i]); }else{ c[i] = o[i]; } } return c; }
而深复制则不同,它不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上。这就不会存在obj和shallowObj的arr属性指向同一个对象的问题。
这样obj1和obj2分别拥有不同的内存地址,两边的值改变互不影响。
---------------------------------------------------------------------------------------------------------------------------------
浅拷贝实现:
var a = [1, 2, 3, 4, 5]; var b = a; a[0] = 2 console.log(a); console.log(b); //因为b浅拷贝a, ab指向同一个内存地址(堆内存中存的值) //b会随着a的变化而变化 //[2, 2, 3, 4, 5] //[2, 2, 3, 4, 5]
深拷贝实现:
function deepCopy(obj){ var objClone = Array.isArray(obj) ? [] : {}; if(obj && typeof(obj) === "object"){ for(var key in obj){ //检测obj对象是否含有key的属性或对象 if(obj.hasOwnProperty(key)){ if(obj[key] && typeof(obj[key]) === "object"){ objClone[key] = deepCopy(obj[key]); }else{ objClone[key] = obj[key]; } } } return objClone; } } var a = [1, 2, 4, 6, "a", "12", [1, 2]]; var b = deepCopy(a); a[4] = 7; console.log(a); console.log(b); //b对象并没有因为a对象的改变而改变,因为b深拷贝a //[1, 2, 4, 6, 7, '12', [1, 2]] //[1, 2, 4, 6, 'a', '12', [1, 2]]