JavaScript中对象深度克隆的最高效方法
JavaScript中对象深度克隆的最高效方法
技术背景
在JavaScript编程中,对象克隆是一个常见的需求。浅克隆只复制对象的一层属性,而深度克隆会递归地复制对象的所有属性,包括嵌套对象。不同的克隆方法适用于不同的场景,了解它们的优缺点对于编写高效、可靠的代码至关重要。
实现步骤
原生深度克隆
现在所有主流浏览器和Node.js >= 17都支持structuredClone(value)
函数,对于旧系统也有polyfills可用。
1 |
|
如果需要,可先加载polyfill:
1 |
|
不过,该方法有一些限制:
- 函数对象无法通过结构化克隆算法复制,尝试复制会抛出
DataCloneError
异常。 - 克隆DOM节点同样会抛出
DataCloneError
异常。 - 某些对象属性不会被保留,如
RegExp
对象的lastIndex
属性、属性描述符、setter、getter等。
有数据丢失的快速克隆 - JSON.parse/stringify
如果对象中不包含Date
、函数、undefined
、Infinity
、RegExp
、Map
、Set
、Blob
、FileList
、ImageData
、稀疏数组、类型化数组或其他复杂类型,可使用JSON.parse(JSON.stringify(object))
进行深度克隆。
1 |
|
使用库进行可靠克隆
许多主流库都提供了对象克隆的函数,如:
- Lodash -
cloneDeep
:如果未使用其他提供深度克隆函数的库,这可能是最佳选择。
1 |
|
- Ramda -
clone
- AngularJS -
angular.copy
- jQuery -
jQuery.extend(true, { }, oldObject)
- just library -
just-clone
单行程代码的非深度克隆
Object.assign
方法可用于浅克隆对象:
1 |
|
对于不支持Object.assign
的旧浏览器,可使用以下polyfill:
1 |
|
数组的深度克隆
根据数组元素的类型不同,有不同的深度克隆方法:
- 仅包含原始值的数组:可使用扩展运算符
...
、slice()
、splice(0)
、concat()
等。
1 |
|
- 包含原始值和对象字面量的数组:可使用
JSON.parse(JSON.stringify())
。
1 |
|
- 包含原始值、对象字面量和原型的数组:可编写自定义函数或使用第三方工具函数。
1 |
|
最佳实践
- 如果对象不包含复杂类型,且对性能要求较高,可优先使用
JSON.parse(JSON.stringify())
。 - 如果需要处理复杂类型(如
Date
、RegExp
等),建议使用structuredClone
或第三方库(如Lodash的cloneDeep
)。 - 在性能敏感的场景下,可编写自定义的克隆函数。
常见问题
JSON.parse(JSON.stringify())
的局限性:该方法会丢失Date
、函数、undefined
、Infinity
、RegExp
等类型的数据,且不能处理循环引用。Object.assign
的浅克隆问题:Object.assign
只进行浅克隆,对于嵌套对象,修改原对象的嵌套属性会影响克隆对象。- 结构化克隆的限制:结构化克隆不能复制函数对象和DOM节点,且某些对象属性不会被保留。
JavaScript中对象深度克隆的最高效方法
https://119291.xyz/posts/2025-05-08.most-efficient-way-to-deep-clone-object-in-javascript/