JavaScript深拷贝与浅拷贝:区别及实现方法详解
在JavaScript中,深拷贝和浅拷贝是两种不同的对象复制方式,它们的主要区别在于复制过程中是否创建了新的对象实例以及是否递归地复制了对象中的所有属性(包括嵌套对象)。
浅拷贝
浅拷贝是指创建一个新的对象,这个新对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型(比如字符串、数字、布尔值),拷贝的就是值本身。但如果属性是引用类型(比如对象、数组),拷贝的就是内存地址,即指向同一个对象。因此,如果修改了新对象中的某个引用类型属性,原始对象中的对应属性也会受到影响。
JavaScript中常见的浅拷贝方法包括:
Object.assign()
- 展开运算符(
...
)
深拷贝
深拷贝是指创建一个新的对象,并且递归地复制原始对象中的所有属性(包括嵌套对象),使得新对象和原始对象完全独立。修改新对象中的任何属性都不会影响原始对象。
JavaScript中实现深拷贝的方法有多种,以下是几种常见的方式:
-
使用JSON对象
这种方法简单直接,但有一些限制,比如无法复制函数、
undefined
、Symbol
等,也无法处理循环引用。const deepCopy = JSON.parse(JSON.stringify(originalObject));
-
递归拷贝
通过递归函数手动实现深拷贝,可以处理更复杂的对象和情况,但需要编写额外的代码。
function deepCopy(obj, hash = new WeakMap()) {if (Object(obj) !== obj || obj === null) {return obj; // 处理原始值和非对象}if (hash.has(obj)) {return hash.get(obj); // 处理循环引用}let copy;if (Array.isArray(obj)) {copy = [];hash.set(obj, copy);for (let i = 0; i < obj.length; i++) {copy[i] = deepCopy(obj[i], hash);}} else {copy = {};hash.set(obj, copy);for (const key in obj) {if (Object.prototype.hasOwnProperty.call(obj, key)) {copy[key] = deepCopy(obj[key], hash);}}}return copy; }
-
使用第三方库
如
lodash
的_.cloneDeep()
方法,可以方便地实现深拷贝,但会增加项目的依赖。const _ = require('lodash'); const deepCopy = _.cloneDeep(originalObject);
选择哪种方法取决于具体的需求和场景。如果对象结构比较简单且没有特殊类型(如函数、循环引用等),使用JSON对象的方法可能足够。如果需要处理更复杂的情况,递归拷贝或第三方库可能是更好的选择。