javascript深拷贝如何实现_有哪些常见的方法与陷阱?
发布时间 - 2026-01-05 00:00:00 点击率:次JSON.parse(JSON.stringify(obj))不能当深拷贝用,因会丢弃函数、undefined、Symbol等,且无法处理循环引用;structuredClone()是目前最靠谱的原生方案,但不支持函数、undefined、Symbol;手写需注意特殊类型识别与循环引用缓存;Lodash的_.cloneDeep()覆盖广但不深拷贝函数体、不保留原型。
JSON.parse(JSON.stringify(obj)) 为什么不能当深拷贝用?
它看起来最简单,但实际只适合纯数据对象——没有函数、undefined、Symbol、Date、RegExp、Map、Set、BigInt,也不能处理循环引用。JSON.stringify() 遇到这些值会静默丢弃或报错,比如:undefined 和函数直接被忽略,Date 变成字符串,NaN 变成 null。
常见错误现象:
-
JSON.parse(JSON.stringify({ time: new Date() }))→{ time: "2025-01-01T00:00:00.000Z" }(不再是Date实例) -
JSON.parse(JSON.stringify({ fn() {} }))→{}(函数消失) -
const obj = {}; obj.self = obj; JSON.stringify(obj)→ 报错TypeError: Converting circular structure to JSON
structuredClone() 是目前最靠谱的原生方案吗?
是的,但它有明确
的浏览器兼容性边界和类型限制。structuredClone() 支持 Date、RegExp、Map、Set、ArrayBuffer、TypedArray、BigInt、Object、Array 等,也支持循环引用,且保持原型链无关(即结果总是 plain object/array)。
使用注意点:
立即学习“Java免费学习笔记(深入)”;
- 不支持函数、
undefined、Symbol—— 遇到会抛错:DataCloneError: function is not supported - Node.js 17+ 默认启用,但需开启
--enable-structured-cloning标志;Node.js 18.13+ 和 20.6+ 已默认启用 - 浏览器中 Chrome 98+、Firefox 94+、Safari 16.4+ 支持;IE 完全不支持
const original = { date: new Date(), map: new Map([['a', 1]]), self: null };
original.self = original;
const cloned = structuredClone(original); // ✅ 成功,cloned.self 指向 cloned 自身
手写递归深拷贝时最容易漏掉什么?
不是“递归调用”本身,而是对特殊内置对象和边界类型的识别与分发。比如只判断 typeof obj === 'object' 会把 null、Array、Date、RegExp 全部混为一谈。
关键判断逻辑应优先使用 Object.prototype.toString.call():
-
[object Array]→ 用map+ 递归 -
[object Date]→new Date(obj.getTime()) -
[object RegExp]→new RegExp(obj)(注意 flags) -
[object Map]→new Map([...obj].map(([k, v]) => [k, deepClone(v)])) -
null要单独处理,否则Object.keys(null)报错 - 循环引用必须缓存已拷贝的源对象映射,否则栈溢出
function deepClone(obj, seen = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj;
if (seen.has(obj)) return seen.get(obj);
const tag = Object.prototype.toString.call(obj);
let cloned;
if (tag === '[object Array]') {
cloned = [];
} else if (tag === '[object Date]') {
cloned = new Date(obj.getTime());
} else if (tag === '[object RegExp]') {
cloned = new RegExp(obj.source, obj.flags);
} else {
cloned = {};
}
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() 真的能覆盖所有场景?
它比手写健壮得多,支持函数(浅拷贝函数引用)、undefined、Symbol、Error、Promise、DOM 节点等,也处理循环引用。但要注意两点:
- 它不会深拷贝函数体,只是复制引用 —— 这是设计选择,不是 bug
- 它不 clone
prototype上的属性,也不保留构造器,结果始终是 plain object/array/类数组 - 体积较大(约 15KB minzipped),如果项目已用 Webpack/Rollup,建议按需引入:
import cloneDeep from 'lodash-es/cloneDeep';
真正容易被忽略的是:当你依赖某个库内部用了 _.cloneDeep(),而你传入了自定义类实例(如 class User {}),它只会拷贝可枚举属性,不会调用 User 的 constructor 或 getter/setter —— 这不是缺陷,是通用工具的合理取舍。
# javascript
# java
# js
# node.js
# json
# node
# 浏览器
# 工具
# safari
# 栈
# ai
# 为什么
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
如何正确选择百度移动适配建站域名?
EditPlus中的正则表达式实战(5)
Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】
如何快速登录WAP自助建站平台?
Laravel如何实现数据导出到CSV文件_Laravel原生流式输出大数据量CSV【方案】
如何用ChatGPT准备面试 模拟面试问答与职场话术练习教程
香港服务器部署网站为何提示未备案?
Laravel如何实现RSS订阅源功能_Laravel动态生成网站XML格式订阅内容【教程】
JS碰撞运动实现方法详解
Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives
Laravel观察者模式如何使用_Laravel Model Observer配置
如何用手机制作网站和网页,手机移动端的网站能制作成中英双语的吗?
Android中AutoCompleteTextView自动提示
Laravel怎么使用Intervention Image库处理图片上传和缩放
javascript基本数据类型及类型检测常用方法小结
如何在IIS中配置站点IP、端口及主机头?
详解jQuery停止动画——stop()方法的使用
Laravel如何使用Gate和Policy进行授权?(权限控制)
php打包exe后无法访问网络共享_共享权限设置方法【教程】
中山网站制作网页,中山新生登记系统登记流程?
iOS正则表达式验证手机号、邮箱、身份证号等
原生JS获取元素集合的子元素宽度实例
网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?
Laravel如何使用Laravel Vite编译前端_Laravel10以上版本前端静态资源管理【教程】
今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】
如何在IIS7上新建站点并设置安全权限?
Android Socket接口实现即时通讯实例代码
如何快速搭建高效可靠的建站解决方案?
如何用AI一键生成爆款短视频文案?小红书AI文案写作指令【教程】
香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧
使用spring连接及操作mongodb3.0实例
如何在建站宝盒中设置产品搜索功能?
Laravel如何获取当前用户信息_Laravel Auth门面获取用户ID
Laravel怎么配置.env环境变量_Laravel生产环境敏感数据保护与读取【方法】
Laravel如何实现本地化和多语言支持?(i18n教程)
Laravel如何与Inertia.js和Vue/React构建现代单页应用
个人网站制作流程图片大全,个人网站如何注销?
Python企业级消息系统教程_KafkaRabbitMQ高并发应用
Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用
laravel怎么配置和使用PHP-FPM来优化性能_laravel PHP-FPM配置与性能优化方法
如何在阿里云高效完成企业建站全流程?
Laravel如何升级到最新的版本_Laravel版本升级流程与兼容性处理
Laravel Sail是什么_基于Docker的Laravel本地开发环境Sail入门
如何在腾讯云服务器上快速搭建个人网站?
Laravel项目怎么部署到Linux_Laravel Nginx配置详解
如何用景安虚拟主机手机版绑定域名建站?
如何快速搭建安全的FTP站点?
Laravel如何配置任务调度?(Cron Job示例)
Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】
桂林网站制作公司有哪些,桂林马拉松怎么报名?

