JavaScript深拷贝几种实现方式
时间:2026-01-11 14:36:50 404浏览 收藏
在IT行业这个发展更新速度很快的行业,只有不停止的学习,才不会被行业所淘汰。如果你是文章学习者,那么本文《JavaScript深拷贝实现方法有哪些》就很适合你!本篇内容主要包括##content_title##,希望对大家的知识积累有所帮助,助力实战开发!
JavaScript深拷贝无万能方案:structuredClone()支持多数内置类型且处理循环引用,但不支持function等;手写需防null、数组遍历、循环引用等陷阱;Lodash cloneDeep覆盖广但有体积和兼容性考量;JSON方法仅适用于纯数据对象。

JavaScript 深拷贝没有“银弹”,JSON.parse(JSON.stringify(obj)) 看似简单,但会丢函数、undefined、Symbol、Date、RegExp、Map、Set、循环引用等;真正可靠的方式得按场景选。
用 structuredClone() —— 现代浏览器首选
这是目前最接近“开箱即用”的原生深拷贝方案,支持大多数内置类型(包括 Date、RegExp、Map、Set、ArrayBuffer、TypedArray),且能处理循环引用。
注意点:
- Node.js 17+ 默认启用,18.10+ 稳定;低于此版本需加
--experimental-structured-cloning标志 - 不支持
function、undefined、Symbol、Promise、Error实例(会抛错或跳过) - 不能拷贝带有
prototype方法的自定义类实例(只保留数据属性)
const obj = { a: 1, b: new Date(), c: new Map([[1, 'x']]) };
const cloned = structuredClone(obj); // ✅ 安全、快、语义清晰
手写递归 + 类型判断 —— 需要完全控制逻辑时
当你要保留 function、undefined、Symbol,或需对特定字段做定制处理(如忽略某些 key、转换日期格式),就得自己实现。关键不是“写全所有类型”,而是明确你的数据契约。
常见陷阱:
- 忘记处理
null(它 typeof 是"object",但不是对象) - 用
for...in遍历数组,导致索引变成字符串、丢失稀疏性 - 没用
Object.prototype.toString.call()或Array.isArray()判数组,误把类数组当普通对象 - 没缓存已遍历对象,遇到循环引用直接栈溢出
function deepClone(obj, seen = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj;
if (seen.has(obj)) return seen.get(obj);
const cloned = Array.isArray(obj) ? [] : {};
seen.set(obj, cloned);
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
cloned[key] = deepClone(obj[key], seen);
}
}
return cloned;
}
用第三方库 —— Lodash 的 cloneDeep() 最常用
它覆盖了绝大多数边界情况:Buffer、Promise、HTML 元素、arguments、带 constructor 的对象等。但要注意体积和 tree-shaking 支持。
使用前确认:
- 是否真需要它支持的所有类型?比如纯 JSON 数据流,
structuredClone更轻量 - 项目是否已引入 Lodash?避免只为一个函数引入整包(可用
lodash.clonedeep单独安装) - 某些环境(如 Deno 或严格 CSP)可能禁用
eval或Function构造器,而 Lodash 内部有动态代码生成逻辑(极少数情况)
import cloneDeep from 'lodash.clonedeep';
const data = { fn: () => {}, date: new Date() };
const copied = cloneDeep(data); // ✅ fn 被保留为 function,date 正确复制
为什么不用 JSON.parse(JSON.stringify())?
它只适合“纯数据对象”——即键值全是字符串、数字、布尔、null、普通数组或嵌套对象。一旦出现以下任一,结果就不可靠:
undefined和function字段直接被忽略Symbol键被丢弃Date变成字符串("2024-05-20T12:00:00.000Z"),不再是Date实例NaN、Infinity变成null- 循环引用直接报错:
TypeError: Converting circular structure to JSON
const bad = { a: undefined, b: () => {}, c: Symbol('x'), d: new Date() };
console.log(JSON.parse(JSON.stringify(bad))); // { d: "2024-05-20T12:00:00.000Z" } —— 其他全没了
深拷贝真正的复杂点不在“怎么写”,而在“你到底想拷什么”。函数要不要?原型链要不要?特殊对象(如 canvas 上下文)要不要?先画清数据边界,再选工具,比背方法更重要。
今天关于《JavaScript深拷贝几种实现方式》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!
-
502 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
373 收藏
-
368 收藏
-
267 收藏
-
340 收藏
-
401 收藏
-
474 收藏
-
152 收藏
-
243 收藏
-
404 收藏
-
397 收藏
-
466 收藏
-
127 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习