作者:Mike丶
https://www.cnblogs.com/mikeCao/p/8710837.html
深拷貝和淺拷貝最根本的區別在於是否真正獲取一個對象的復制實體,而不是引用。
假設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 deepClone(obj) { var newObj = obj instanceof Array ? []:{}; if(typeof obj !== 'object') { return obj; }else{ for(var i in obj) { newObj[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]; } } return newObj; } var a = [1, 2, 4, 6, "a", "12", [1, 2]]; var b = deepClone(a); a[3] = 7; console.log(a); console.log(b);
//b對象並沒有因為a對象的改變而改變,因為b深拷貝a
[ 1, 2, 4, 7, 'a', '12', [ 1, 2 ] ]
[ 1, 2, 4, 6, 'a', '12', [ 1, 2 ] ]