js 中的对象克隆

浅谈 js 中浅克隆和深克隆的方法。

浅克隆

一般来说浅克隆有两种方法

  • 扩展运算符
  • Object.assign()
let obj = {
  arr: [1, 2],
};

let clone1 = { ...obj };
let clone2 = Object.assign({}, obj);

clone1.arr[0] = 10;
clone2.arr[1] = 20;

console.log(obj.arr); // [10, 20]

上面的代码类似于以下的 js 实现

function shallowClone(oriObj) {
  let clone = {};
  for (let key in oriObj) {
    clone[key] = oriObj[key];
  }
  return clone;
}

可以看到,在使用这些方法克隆同一个对象之后,各自更改自身属性中 arr 的值的时候,大家却同时发生了改变。这是因为此时每个对象中的 arr 属性不是存着同一个 arr 的副本,而是指向同一个 arr 的指针。

追求完美一点可以使用 es6 的 Object.setPrototypeOf() 使原型保持一致

所以上面或者类似的克隆对象的方法,我们一般称之为浅克隆。

深克隆

下面简单说一下深克隆的方法

JSON.stringify()

先使用 JSON.stringify(obj)将对象转换成字符串,然后再通过 JSON.parse()转回来,这是最简单粗暴的办法,但是如果不是标准 JSON 格式的属性在转换过程中将会丢失,例如 function。

递归

递归就是碰到 value 为 object 时,按照需求进一步克隆。一般有以下几点考虑:

  • Array、function、reg 和 Date 等特殊情况
  • 循环引用导致堆栈溢出问题
  • 是否需要克隆原型