在JavaScript中处理对象和数组时,理解拷贝行为是避免意外副作用的关键。拷贝分为浅拷贝与深拷贝,其核心区别在于对嵌套对象引用地址的处理方式。
![图片[1]-如何实现深拷贝和浅拷贝?-速码派](http://www.sumapai.com/wp-content/uploads/2026/01/e6c709f1d20245b9b7a5d6b0d00f5272tplv-tb4s082cfz-aigc_resize_1080_1080.webp)
什么是浅拷贝
浅拷贝创建一个新对象,并将原对象顶层属性的值复制到新对象。如果属性值是基本类型,则直接复制值;如果是引用类型(如对象、数组),则复制其内存地址。这意味着新旧对象会共享嵌套的对象。
const original = { a: 1, b: { c: 2 } };
const shallowCopy = { ...original };
original.a = 10;
original.b.c = 20;
console.log(shallowCopy.a); // 1 (未受影响)
console.log(shallowCopy.b.c); // 20 (共享对象被修改)
常见的浅拷贝方法包括使用扩展运算符...、Object.assign({}, obj)以及数组的slice()或concat()方法。
什么是深拷贝
深拷贝会创建一个全新的对象,并递归地复制原对象中的所有层级,确保新旧对象完全独立,不共享任何引用类型的属性。
const original = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(original));
original.b.c = 20;
console.log(deepCopy.b.c); // 2 (完全独立,未受影响)
使用JSON.stringify和JSON.parse是实现简单深拷贝的快捷方式。但这种方法存在局限性:它会忽略函数、undefined、Symbol和循环引用,同时会将Date对象转为字符串。
实现一个健壮的深拷贝函数
为了处理更复杂的情况,需要实现一个递归拷贝函数。基础版本如下,但需要注意处理循环引用等边界情况。
function deepClone(source) {
if (source === null || typeof source !== 'object') {
return source;
}
const target = Array.isArray(source) ? [] : {};
for (let key in source) {
if (source.hasOwnProperty(key)) {
target[key] = deepClone(source[key]);
}
}
return target;
}
这个函数递归地复制所有自身可枚举属性。在实际生产环境中,还需要考虑拷贝原型链、处理Date、RegExp等内置对象,以及使用WeakMap解决循环引用问题,防止栈溢出。
在项目中选择拷贝方式时,需要权衡需求与性能。如果数据没有嵌套引用或你确实需要共享嵌套对象,使用浅拷贝。如果需要完全独立的数据副本,且数据是简单的JSON结构,JSON方法很方便。对于包含复杂类型或需要高性能的场景,建议使用成熟的工具库如Lodash中的_.cloneDeep方法,它们已经妥善处理了各种边界情况。






















暂无评论内容