1. 程式人生 > >淺拷貝和深拷貝(陣列和物件的深淺拷貝)

淺拷貝和深拷貝(陣列和物件的深淺拷貝)

 淺拷貝

只是拷貝了基本型別的資料,而引用型別資料,複製後也是會發生引用,我們把這種拷貝叫做淺拷貝(淺複製)

物件淺拷貝:

var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = obj1;
obj2.b = 100;
console.log(obj1);
// { a: 10, b: 100, c: 30 } <-- b 被改到了
console.log(obj2);
// { a: 10, b: 100, c: 30 }

陣列淺拷貝:

var arr = ["One","Two","Three"];
var arrto = arr;
arrto[1] = "test";
console.log("陣列的原始值:" + arr + "<br />");//陣列的原始值:One,test,Three
console.log("陣列的新值:" + arrto + "<br />");//陣列的新值:One,test,Three

深拷貝

深拷貝:在計算機中開闢了一塊新的記憶體地址用於存放複製的物件。(對屬性中所有引用型別的值,遍歷到是基本型別的值為止。 )

物件的深拷貝

方式一:簡單的物件(不算是真正的深拷貝)

var a = {name:'1',age:'2',color:'3'};
function copyObj(a) {
var b = {};
for(var key in a) {
b[key] = a[key];
}
return b;
}
var c = copyObj(a);
c.name = '5';
console.log('c',c);
console.log('a',a);

方式二: ES6  let {...b} = a

方式三:複雜物件,利用遞迴來實現深拷貝(最常用的)

function cloneObject (obj) {
     var newObj = {}  //如果不是引用型別,直接返回
      if (typeof (obj) !== 'object') {
          return obj
     }
     //如果是引用型別,遍歷屬性
    else{
        for (var attr in obj) {
        //如果某個屬性還是引用型別,遞迴呼叫
        newObj[attr] = cloneObject(obj[attr])
                }
       }
    return newObj
}

我們先判斷它是否為引用型別,如果不是,直接返回 
如果是,迴圈遍歷該物件的屬性,如果某個屬性還是引用型別,則針對該屬性再次呼叫cloneObject函式 

方式四:用JSON.stringify把物件轉成字串,再用JSON.parse把字串轉成新的物件。(最常用的)

var obj1 = { body: { a: 10 } };
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.body.a = 20;
console.log(obj1);
// { body: { a: 10 } } <-- 沒被改到
console.log(obj2);
// { body: { a: 20 } }
console.log(obj1 === obj2);
// false
console.log(obj1.body === obj2.body);
// false

陣列深拷貝

ES5:slice()和concat()

var a = [1,2,3];
var b = a.slice(0);
var c = a.concat();
b.push(4);
c.push(5);
a; //[1,2,3]
b; //[1,2,3,4]
c; //[1,2,3,5]

ES6:   let [...b] = a;