查流量网站,网站开发的毕业设计,淘宝客网站如何做推广方案,wordpress软件门户主题在前端开发中#xff0c;深克隆#xff08;Deep Clone#xff09;和浅克隆#xff08;Shallow Clone#xff09;是常见的操作。浅克隆和深克隆的区别主要体现在对象内部嵌套对象的处理方式上。
1. 浅克隆#xff08;Shallow Clone#xff09;
浅克隆是指创建一个新对象…在前端开发中深克隆Deep Clone和浅克隆Shallow Clone是常见的操作。浅克隆和深克隆的区别主要体现在对象内部嵌套对象的处理方式上。
1. 浅克隆Shallow Clone
浅克隆是指创建一个新对象但对于原对象中嵌套的对象浅克隆只复制它们的引用而不是创建新的对象。换句话说浅克隆只是“浅复制”了对象的属性嵌套的对象还是共享相同的引用。 // 浅克隆
const shallowClone (obj) {return { ...obj };
};// 或者使用 Object.assign
const shallowClone2 (obj) {return Object.assign({}, obj);
};const obj1 { name: John, address: { city: NY } };
const obj2 shallowClone(obj1);obj2.address.city LA;console.log(obj1.address.city); // 输出 LA
console.log(obj2.address.city); // 输出 LA2. 深克隆Deep Clone
深克隆是指创建一个新对象并且递归地复制原对象中的所有属性包括嵌套的对象嵌套对象也会被克隆为新的对象。这样修改新对象不会影响到原对象反之亦然。
1. 递归实现
// 深克隆实现递归
const deepClone (obj) {if (obj null || typeof obj ! object) return obj;const newObj Array.isArray(obj) ? [] : {}; // 判断是数组还是对象for (let key in obj) {if (obj.hasOwnProperty(key)) {newObj[key] deepClone(obj[key]); // 递归克隆}}return newObj;
};
const obj1 { name: John, address: { city: NY }, hobbies: [reading, gaming] };
const obj2 deepClone(obj1);
obj2.address.city LA;
obj2.hobbies[0] traveling;
console.log(obj1.address.city); // 输出 NY
console.log(obj2.address.city); // 输出 LA
console.log(obj1.hobbies[0]); // 输出 reading
console.log(obj2.hobbies[0]); // 输出 traveling2. JSON 方法
JSON.parse(JSON.stringify(...)) 是前端开发中常用的一种快速实现深克隆的方法但它也有一些缺陷。
const deepCloneUsingJSON (obj) {return JSON.parse(JSON.stringify(obj));
};const obj1 { name: John, address: { city: NY }, hobbies: [reading, gaming] };
const obj2 deepCloneUsingJSON(obj1);obj2.address.city LA;
obj2.hobbies[0] traveling;console.log(obj1.address.city); // 输出 NY
console.log(obj2.address.city); // 输出 LA
console.log(obj1.hobbies[0]); // 输出 reading
console.log(obj2.hobbies[0]); // 输出 traveling3. JSON.stringify 的缺陷
尽管其是一种快速且简单的深克隆方法但它也有几个明显的缺陷
1、无法克隆函数JSON 序列化过程会丢失对象中的函数。例如
const obj1 { name: John, greet: () console.log(Hello) };
const obj2 JSON.parse(JSON.stringify(obj1));
console.log(obj2); // { name: John }
obj2.greet(); // 报错obj2.greet is not a function2、无法处理 undefined对象中的 undefined 值会被丢失并且会在序列化过程中变成 null。
const obj1 { value: undefined };
const obj2 JSON.parse(JSON.stringify(obj1));console.log(obj2.value); // 输出: undefined3、无法处理特殊对象某些 JavaScript 特殊对象如 Date、RegExp、Map、Set、Promise 等无法正确克隆变成普通的对象或丢失其原有属性。
const obj1 { date: new Date(), map: new Map() };
const obj2 JSON.parse(JSON.stringify(obj1));console.log(obj2); // { date: 2025-01-08T06:39:12.842Z, map: {} }
console.log(obj2.date instanceof Date); // 输出: false
console.log(obj2.map instanceof Map); // 输出: false
4、循环引用无法处理如果对象包含循环引用即一个对象的属性引用了它自身JSON.stringify 会抛出错误。
const obj1 {};
obj1.self obj1;const obj2 JSON.parse(JSON.stringify(obj1));
// 报错TypeError: Converting circular structure to JSON 无法转换递归结构4. 深度克隆的缺陷和完善
在实际开发中基于 JSON.stringify 的深克隆方法需要处理一下。
1、处理 undefined 和 null在序列化之前进行预处理避免 undefined 变成 null或者在反序列化时进行特殊处理。
2、处理循环引用为防止循环引用导致的错误可以使用 WeakMap 来存储已访问的对象并在遇到已访问的对象时直接返回避免无限递归。
3、支持 Date、RegExp 等特殊对象在克隆过程中判断对象的类型使用 Object.prototype.toString.call() 来判断进行相应的处理。
5. 更健壮的深克隆代码
// 考虑循环引用
const cache new WeakMap(); // 确保对象在外层销毁时Map结构自动销毁防止内存泄露
const deepClone (obj) {if (obj null || typeof obj ! object) return obj;// obj是对象if (cache.has(obj)) {return cache.get(obj);}const newObj Array.isArray(obj) ? [] : {}; // 判断是数组还是对象cache.set(obj, newObj);// 考虑原型if (Object.getPrototypeOf(obj) ! Object.prototype) {// newObj.__proto__ Object.getPrototypeOf(obj);// orObject.setPrototypeOf(newObj, Object.getPrototypeOf(obj));}for (let key in obj) {// 考虑继承属性if (obj.hasOwnProperty(key)) {newObj[key] deepClone(obj[key]); // 递归克隆}}return newObj;
};
class Person {constructor(name, age) {this.name name;this.age age;}eat() {console.log(eat);}
}
Person.prototype.hobby game;
Person.prototype.say function () {console.log(say);
};
const obj new Person(张三, 18);
// 循环引用
obj.h obj;
console.log(obj);
console.log(deepClone(obj)); // ref *1 Person { name: 张三, age: 18, h: [Circular *1] }总结
1、浅克隆只复制对象的第一层嵌套对象还是共享引用。
2、深克隆递归复制整个对象包括嵌套对象。