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 等特殊情况
- 循环引用导致堆栈溢出问题
- 是否需要克隆原型