- 浅拷贝
- 深拷贝
浅拷贝
浅拷贝是指创建一个新对象,新对象与原始对象共享相同的引用类型的属性(如对象、数组),而基本类型的属性会被完全复制。换句话说,浅拷贝只复制对象的引用,而不复制引用指向的内容。
实现浅拷贝的方法有多种,下面列举几种常见的实现方式:
- 对象扩展运算符(
...
)或Object.assign()
方法:
const originalObject = { name: 'John', age: 30 };
const shallowCopy = { ...originalObject };
// 或
const shallowCopy = Object.assign({}, originalObject);
- 数组的
slice()
方法或concat()
方法:
const originalArray = [1, 2, 3, 4, 5];
const shallowCopy = originalArray.slice();
// 或
const shallowCopy = originalArray.concat();
这些方法会创建一个新的对象或数组,将原始对象的属性复制到新对象中,但如果原始对象的属性是引用类型(如对象、数组),则新对象与原始对象共享相同的引用。这意味着修改新对象的引用类型属性会影响到原始对象。
例如:
const originalObject = { name: 'John', hobbies: ['reading', 'painting'] };
const shallowCopy = { ...originalObject };
shallowCopy.name = 'Jane'; // 修改新对象的基本类型属性不会影响原始对象
shallowCopy.hobbies.push('swimming'); // 修改新对象的引用类型属性会影响原始对象
console.log(originalObject); // { name: 'John', hobbies: ['reading', 'painting', 'swimming'] }
console.log(shallowCopy); // { name: 'Jane', hobbies: ['reading', 'painting', 'swimming'] }
浅拷贝只适用于一层对象的复制,如果对象中的属性仍然是对象或数组,那么这些属性将被共享。
深拷贝
深拷贝是指创建一个新对象,新对象与原始对象完全独立,包括引用类型的属性也会被递归地复制,两个对象之间互不影响。
实现深拷贝的方法有多种,下面列举几种常见的实现方式:
- 使用
JSON.parse(JSON.stringify())
方法(仅适用于 JSON-serializable 对象):
const originalObject = { name: 'John', age: 30 };
const deepCopy = JSON.parse(JSON.stringify(originalObject));
这种方法的优点是简单易用,通过将对象序列化为 JSON 字符串再解析为对象,实现了对象的深拷贝。但需要注意的是,该方法仅适用于 JSON-serializable 对象,即能够被 JSON 格式化的对象,而不能复制包含函数、正则表达式、日期等特殊类型的属性,并且对于循环引用的对象也无法正确处理。
- 使用递归函数来手动复制对象的每个属性,处理对象和数组的嵌套:
// 分享几种深拷贝的方法
// 第一种
function deepClone(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
let clone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
clone[key] = deepClone(obj[key]);
}
}
return clone;
}
const originalObject = { name: 'John', hobbies: ['reading', 'painting'] };
const deepCopy = deepClone(originalObject);
// 第二种
function deepClone(origin, target) {
const localTarget = target || {},
toStr = Object.prototype.toString,
arrStr = "[object Array]";
for(var prop in origin){
if(Object.prototype.hasOwnProperty.call(origin, prop)){
if(origin[prop] !== "null" && typeof(prop) == "object"){
if(toStr.call(origin[prop]) == arrStr){
localTarget[prop] = [];
}
else{
localTarget[prop] = {};
}
//if-else语句可换成
// target[prop] = toStr.call(origin[prop]) == arrStr ? [] : {}; deepClone(origin[prop],localTarget[prop]);
}
else{
localTarget[prop] = origin[prop];
}
}
}
return target;
}
这种方法使用递归函数来手动复制对象的每个属性,当遇到对象或数组时,递归地进行深拷贝。这样可以确保每个属性都是独立的副本,两个对象之间互不影响。
使用递归函数实现深拷贝时,要注意处理循环引用的情况,避免无限递归导致栈溢出。
深拷贝是一种更复杂的拷贝方式,相比浅拷贝,它更适用于复制嵌套对象或数组的情况,确保新对象与原始对象完全独立,不受原始对象的变化影响。但需要注意的是,深拷贝可能会导致性能上的损失,因为需要递归地遍历和复制对象的所有属性。因此,在使用深拷贝时要考虑到性能和内存消耗的问题。
文章中若有不恰当的地方或者有什么需要改进的地方,可以在下方评论,感谢