js2-clone

野生技術協會發表於2020-12-19

js淺克隆和深克隆

1 、什麼是淺克隆? 
只對外部物件進行克隆,不對此物件屬性的值如果也是一個物件,那麼就不進行克隆,如果陣列,只是複製陣列,陣列的內容沒變。 

// 1、物件淺複製
var obj1 = { a: { x: 1 } };
var obj2 = Object.assign({}, obj1);
console.log(obj2);
obj1.a.x = 2;
console.log(obj2);

// 2、陣列淺複製
var arr = [{ x: 0 }, { x: 1 }];
var arr2 = arr.slice();
arr[1].x = 11;
console.log(arr2);

// 3、封裝整合
var clone = function (obj) {
  if (!obj) return obj;
  if (Array.isArray(obj)) {
    return obj.slice();
  } else {
    return Object.assign({}, obj);
  }
}

從例子可以看出,改變clone後的屬性可以影響原有物件,所以是淺clone

二、如何深度clone [deepClone]

2.1 方式,採用json.Stringfy序列化,然後json.pars反序列化

function deepClone1(target) {
  var str = JSON.stringify(target);
  var res = JSON.parse(str);
  return res;
}

 2.2 採用重組物件進行深度複製

function deepClone2(target) {
  if((typeof target !== 'object') || !target) {
    return target;
  }
  let newObj = Array.isArray(target) ? [] : {};
  for (const key in target) {
    if(newObj[key]) {return;} 
    newObj[key] = deepClone2(target[key]);
  }
  return newObj;
}

var obj1 = { a: { x: 1 } };
var obj2 = deepClone2(obj1);
obj1.a.x = 22;
console.log(obj1);
console.log(obj2);

2.3 最終版本(解決迴圈引用的問題)

function deepClone3(target) {
  var temps = [];  // 已經clone的物件
  function mydeepClone(target) {
    if((typeof target != 'object') || !target) {
      return target;
    }
    for (let i = 0; i < array.length; i++) {
      if(temps[i].target == target) {
        return temp[i].copyTarget;
      }
    }
    let obj = Array.isArray(target) ? [] : {};
    Object.keys(target).forEach(key => {
      if (obj[key]) { return; }
      obj[key] = mydeepClone(target[key]);
    });
    return obj;
  }
  return mydeepClone(target);
}

var obj11 = { a: { x: 1 } };
var obj22 = deepClone2(obj11);
obj11.a.x = 22;
console.log(obj11); // 22
console.log(obj22); // 1