JavaScript深拷贝与浅拷贝的区别及实现

深拷贝和浅拷贝是JavaScript中处理对象复制的两种不同方式,它们在处理对象引用时有着显著的区别。
浅拷贝(Shallow Copy)
浅拷贝只复制对象的第一层属性,如果属性是基本类型(如string
、number
、boolean
),则直接复制值;如果属性是引用类型(如object
、array
),则复制引用(即内存地址),而不是复制实际的对象。这意味着,浅拷贝后的对象和原对象共享相同的引用类型属性。
浅拷贝的实现方式:
-
扩展运算符(Spread Operator)
const original = { a: 1, b: { c: 2 } }; const shallowCopy = { ...original };
-
Object.assign
const original = { a: 1, b: { c: 2 } }; const shallowCopy = Object.assign({}, original);
-
数组的
slice
方法const originalArray = [1, 2, { a: 3 }]; const shallowCopyArray = originalArray.slice();
深拷贝(Deep Copy)
深拷贝会递归地复制对象的所有层级,包括嵌套的对象和数组。深拷贝后的对象和原对象完全独立,修改其中一个不会影响另一个。
深拷贝的实现方式:
-
JSON.parse
和JSON.stringify
这是最简单的方式,但有一些限制:- 不能复制函数、
undefined
、Symbol
等特殊类型。 - 不能处理循环引用。
const original = { a: 1, b: { c: 2 } }; const deepCopy = JSON.parse(JSON.stringify(original));
- 不能复制函数、
-
递归实现
手动实现一个递归函数来深拷贝对象:function deepClone(obj) { if (obj === null || typeof obj !== 'object') { return obj; } if (Array.isArray(obj)) { const arrCopy = []; for (let i = 0; i < obj.length; i++) { arrCopy[i] = deepClone(obj[i]); } return arrCopy; } const objCopy = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { objCopy[key] = deepClone(obj[key]); } } return objCopy; } const original = { a: 1, b: { c: 2 } }; const deepCopy = deepClone(original);
-
使用第三方库
一些流行的库如lodash
提供了深拷贝的功能:const _ = require('lodash'); const original = { a: 1, b: { c: 2 } }; const deepCopy = _.cloneDeep(original);
总结
- 浅拷贝:只复制对象的第一层属性,引用类型的属性共享内存地址。
- 深拷贝:递归复制对象的所有层级,引用类型的属性也完全独立。
在实际开发中,选择深拷贝还是浅拷贝取决于具体的需求。如果对象结构简单且不包含嵌套对象或数组,浅拷贝通常足够。如果对象结构复杂或需要完全独立的副本,则应使用深拷贝。