方法 1: オーソドックスなアプローチ(拡張性が高く、推奨)
機能テスト() {
this.a = 1;
this.b = 2;
}
test.prototype.c = 3; // プロトタイプのプロパティ
const obj = 新しいテスト();
console.log("元のオブジェクト", obj);
console.log("オブジェクトのクローン", deepClone(obj));
/** JS 深度克隆
* @param value 需要克隆的值
*/
function deepClone(value) {
// 排除原始类型的情况,函数时也满足此条件
if (typeof value !== "object" || value === null) {
return value;
}
// 克隆结果:1.数组 2.普通对象
const result = Array.isArray(value) ? [] : {};
// 设置克隆结果的原型链为 value 的原型链(即保持原型一致)
Object.setPrototypeOf(result, Object.getPrototypeOf(value));
// 浅层克隆
for (const key in value) {
// 排除原型上的属性
if (value.hasOwnProperty(key)) {
result[key] = deepClone(value[key]); // 针对这个对象的每一个属性值进行克隆,则达到深度克隆效果
}
}
return result;
}
循環参照の問題を解決する
機能テスト() {
this.a = 1;
this.b = 2;
}
test.prototype.c = 3; // プロトタイプのプロパティ
const obj = 新しいテスト();
obj.c = obj; // 循環参照 obj.c は obj 自体と等しい
console.log("元のオブジェクト", obj);
console.log("オブジェクトのクローン", deepClone(obj));
/* 建立缓存区,解决环形引用问题 */
let cache = new WeakMap(); // 使用 WeakMap 为了防止内存泄露
/** JS 深度克隆
* @param value 需要克隆的值
*/
function deepClone(value) {
// 排除原始类型的情况,函数时也满足此条件
if (typeof value !== "object" || value === null) return value;
// 解决环形引用问题(即循环引用)
const cached = cache.get(value);
if (cached) return cached;
// 克隆结果:1.数组 2.普通对象
const result = Array.isArray(value) ? [] : {};
// 设置克隆结果的原型链为 value 的原型链(即保持原型一致)
Object.setPrototypeOf(result, Object.getPrototypeOf(value));
// 环形引用时将克隆的值储存到缓存中
cache.set(value, result);
// 浅层克隆
for (const key in value) {
// 排除原型上的属性
if (value.hasOwnProperty(key)) {
result[key] = deepClone(value[key]); // 针对这个对象的每一个属性值进行克隆,则达到深度克隆效果
}
}
return result;
}
方法 2: JSON のシリアル化と逆シリアル化(スケーラビリティなし)
const obj = { id: 1, name: "张三", age: 18 };
const newObj = JSON.parse(JSON.stringify(obj));
newObj.name = "艾凯";
newObj.age = 22;
console.log("obj", obj);
console.log("newObj", newObj);
機能的には問題ありませんが、このアプローチにはいくつかの明らかな欠陥があります。
このオブジェクトに Map などが含まれている場合、クローン作成後、mapList は Map 構造ではなくなります。
または、このオブジェクトにはいくつかの関数があり、これらの関数はクローン作成後に失われます。
const obj = { id: 1, name: "张三", age: 18, mapList: new Map(), fun: function () { } };
const newObj = JSON.parse(JSON.stringify(obj));
newObj.name = "艾凯";
newObj.age = 22;
console.log("obj", obj);
console.log("newObj", newObj);
方法 3: タブページ通信
非同期で時間がかかり、決して使用されない