
今天我们来探讨下深拷贝的几种实现方式
对象的深拷贝的方法
- Object.assign()
const obj = { a: "a" };
const clone = Object.assign({}, obj);
clone.a = "u";
console.log(obj); // { a: 'a' }
console.log(clone); // { a: 'u' }
注意:Object.assign只适用于一层对象的拷贝,如果对象层级比较多,这个方法就不适用。举个栗子:
const obj = { a: { b: "c" } };
const cloneObj = Object.assign({}, obj);
cloneObj.a.b = "u";
console.log(obj); // { a: { b: "u" } }
console.log(cloneObj); // { a: { b: "u" } }
- JSON.stringfy()和JSON.parse()
const obj = { a: { b: "c" } };
const cloneObj = JSON.parse(JSON.stringify(obj));
cloneObj.a.b = "u";
console.log(obj); // { a: { b: "c" } }
console.log(cloneObj); // { a: { b: "u" } }
- 转换引用地址
const obj = { a: "a" };
const cloneObj = { ...obj };
cloneObj.a = "u";
console.log(obj); // { a: "a" }
console.log(cloneObj); // { a: "u" }
注意,转换引用地址只适用于一层对象的拷贝,如果对象层级比较多,这个方法就不适用。举个栗子:
onst obj = { a: { b: "c" } };
const cloneObj = { ...obj };
cloneObj.a.b = "u";
console.log(obj); // { a: { b: "u" } }
console.log(cloneObj); // { a: { b: "u" } }
- lodash的cloneDeep
import _ from "lodash";
const obj = { a: { b: "c" } };
const cloneObj = _.cloneDeep(obj);
cloneObj.a.b = "u";
console.log(obj); // { a: { b: "c" } }
console.log(cloneObj); // { a: { b: "u" } }
数组的深拷贝的方法
- 转换引用地址
const arr = [1, 2, 3];
const cloneArr = [...arr];
cloneArr[0] = "u";
console.log(arr); // [1, 2, 3]
console.log(cloneArr); // ["u", 2, 3]
- Array.prototype.slice()
const arr = [1, 2, 3];
const cloneArr = arr.slice(0);
cloneArr[0] = "u";
console.log(arr); // [1, 2, 3]
console.log(cloneArr); // ["u", 2, 3]
- Array.prototype.concat()
const arr = [1, 2, 3];
const cloneArr = [].concat(arr);
cloneArr[0] = "u";
console.log(arr); // [1, 2, 3]
console.log(cloneArr); // ["u", 2, 3]
注意,转换引用地址、Array.prototype.slice()、Array.prototype.concat(),只适用于一层且元素都是基本类型的数组拷贝,如果数组比较复杂,这个方法就不适用。
- JSON.stringfy()和JSON.parse()
const arr = [1, 2, 3, { a: "a" }];
const cloneArr = JSON.parse(JSON.stringify(arr));
cloneArr[3].a = "u";
console.log(arr); // [1, 2, 3, { a: "a" }]
console.log(cloneArr); // [1, 2, 3, { a: "u" }]
- lodash的cloneDeep
import _ from "lodash";
const arr = [1, 2, 3, { a: "a" }];
const cloneArr = _.cloneDeep(arr);
cloneArr[3].a = "u";
console.log(arr); // [1, 2, 3, { a: "a" }]
console.log(cloneArr); // [1, 2, 3, { a: "u" }]
数组实现深拷贝的方法还有很多,这里就不一一展示了,有些方法有限制,注意一点就好。
下面我们来手写一个深拷贝的 cloneDeep 方法,适用于任何数组和对象的深拷贝。一起来看下它的实现
function cloneDeep(data) {
// 判断传入的值类型
if (!data) {
return data;
}
if (typeof data !== "object") return data;
if (data.constructor === Date) return new Date(data);
if (data.constructor === RegExp) return new RegExp(data);
// 开始克隆
const clone = Array.isArray(data) ? [] : {};
for (let key in data) {
// 不克隆原型链上的属性和方法
if (data.hasOwnProperty(key)) {
if (typeof data[key] === "object") {
clone[key] = cloneDeep(data[key]);
} else {
clone[key] = data[key];
}
}
}
return clone;
}
const arr = [1, 2, 3, { a: "b" }, [{ c: "d" }]];
const cloneArr = cloneDeep(arr);
cloneArr[3].a = "u";
cloneArr[4][0].c = "uu";
console.log(arr); // [1, 2, 3, { a: "b" }, [{ c: "d" }]]
console.log(cloneArr); // [1, 2, 3, { a: "u" }, [{ c: "uu" }]]
总结
js深拷贝就介绍到这里,感兴趣的小伙伴可以在评论区交流哦。