總結js實現對象數組的淺拷貝和深拷貝

深拷貝 VS 淺拷貝

深拷貝和淺拷貝都是針對的引用類型,JS中的變量類型分爲值類型(基本類型)和引用類型;對值類型進行復制操作會對值進行一份拷貝,而對引用類型賦值,則會進行地址的拷貝,最終兩個變量指向同一份數據。

// 基本類型
var a = 1;
var b = a;
a = 2;
console.log(a, b); // 2, 1 ,a b指向不同的數據

// 引用類型指向同一份數據
var a = {c: 1};
var b = a;
a.c = 2;
console.log(a.c, b.c); // 2, 2 全是2,a b指向同一份數據

對於引用類型,會導致a b指向同一份數據,此時如果對其中一個進行修改,就會影響到另外一個,有時候這可能不是我們想要的結果,如果對這種現象不清楚的話,還可能造成不必要的bug

那麼如何切斷a和b之間的關係呢,可以拷貝一份a的數據,根據拷貝的層級不同可以分爲淺拷貝和深拷貝,淺拷貝就是隻進行一層拷貝,深拷貝就是無限層級拷貝

淺拷貝的實現方式

方法一:通用循環

function shallowCopy(obj) {
  if (typeof obj !== 'object') return;

  const newObj = obj instanceof Array ? [] : {};

  for(let key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = obj[key];
    }
  }

  return newObj;
}

方法二:Object.assign

let a1 = ['hello', '2018']
let b1 = Object.assign([], a1)
// 改變b1中的值
b1[0] = 'hi'
/**
 * 輸出結果發現
 * 改變b1數據
 * a1數組沒有改變,b1數組改變
 */
console.log(a1) // ['hello', '2018']
console.log(b1) // ['hi', '2018']
let a2 = [
  {
    name: 'java',
    count: 12
  },
  {
    name: 'js',
    count: 13
  }
]
let b2 = Object.assign([], a2)
// 改變b2數組中其中對象的count值
b2[0].count = 111
/**
 * 輸出結果發現
 * 改變了b2數據
 * a1,b1數組都發生了改變
 */
console.log(a2)
console.log(b2)

---輸出結果

方法三:Array.slice

var arr1 = ["前端","安卓","蘋果"];
var arr2 = arr1.slice(0);
arr2[0] = "後端";
console.log("原始值:" + arr1 );//前端,安卓,蘋果
console.log("新值:" + arr2);//後端,安卓,蘋果

通過JS的slice方法,改變拷貝出來的數組的某項值後,對原來數組沒有任何影響。

缺點:適用於對不包含引用對象的一維數組的深拷貝

方法四:Array.concat

var arr1 = ["前端","安卓","蘋果"];
var arr2 = arr1.concat();
arr2[0] = "後端";
console.log("原始值:" + arr1 );//前端,安卓,蘋果
console.log("新值:" + arr2);//後端,安卓,蘋果

concat方法,原數組和新數組修改某值後,不會改變。

缺點:適用於對不包含引用對象的一維數組的深拷貝

方法五:Array.concat

let arr1 = ['ES6', 'let', 'const']
let arr2 = [...arr1]
arr2[0] = 'JavaScript'
console.log(arr1)
console.log(arr2)

深拷貝的實現方式

方法一:JSON.parse(JSON.stringify())

function cloneJSON(source) {
    return JSON.parse(JSON.stringify(source));
}

方法二:通用循環遞歸調用

function deepCopy(obj) {
  if (typeof obj !== 'object') return;

  const newObj = obj instanceof Array ? [] : {};

  for(let key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = typeof obj === 'object' ? deepCopy(obj[key]) : obj[key];
    }
  }

  return newObj;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章