优先用 structuredClone()(现代环境首选),它能正确处理 Date、RegExp、Map、Set 等并自动解决循环引用,但不支持 function 和 undefined;老环境或需保留函数时选 Lodash _.cloneDeep()。

图表配置项通常结构复杂,含嵌套对象、数组、函数(如 formatter、onClick 回调)、Date、正则、Symbol,甚至可能有循环引用(比如配置中引用了自身实例)。直接用 JSON.parse(JSON.stringify(obj)) 会丢掉函数、undefined、Symbol、Date 原始类型,还会让 new Date() 变成字符串、/abc/g 变成空对象,严重破坏图表行为。
优先用 structuredClone()(现代环境首选)
如果你的项目运行在 Chrome 98+、Firefox 94+、Safari 15.4+ 或 Node.js 18.12+,structuredClone() 是最稳妥的原生方案:
- ✅ 正确保留
Date、RegExp、Map、Set、ArrayBuffer、Error - ✅ 自动检测并处理循环引用(不会栈溢出或报错)
- ❌ 不支持
function和undefined—— 但图表配置中函数多为回调,克隆后本就不该执行原逻辑;undefined字段丢失一般不影响渲染 - ⚠️ 注意:若配置里含自定义类实例(如 ECharts 的
echarts.graphic.LinearGradient),它无法识别,会抛DataCloneError
兼容老环境或需保留函数时,用 Lodash _.cloneDeep()
当必须支持 IE 或需要完整保留函数引用(例如你打算复用 formatter 逻辑)、Symbol 键、不可枚举属性时,_.cloneDeep() 仍是生产环境最可靠的选择:
- ✅ 支持
function(浅拷贝引用,符合预期) - ✅ 保留
undefined、Symbol键、Error、RegExp、Date、Map、Set等 - ✅ 自动处理循环引用,且对大型配置项性能较稳
- ⚠️ 体积较大(约 70KB gzip),可考虑轻量替代如
klona(仅支持基础类型 + 循环引用,不支持函数/Symbol)
手写深拷贝要绕开三大坑
若因特殊需求必须手写(如定制化过滤字段、跳过某些子配置),务必处理:
立即学习“Java免费学习笔记(深入)”;
-
循环引用:用
WeakMap缓存已克隆对象,每次进入前先查,避免无限递归 -
类型误判:不用
typeof obj === 'object'(null、Array、Date都返回'object'),改用Array.isArray()、obj instanceof Date、Object.prototype.toString.call(obj) -
特殊对象重建:
-
Date→new Date(obj.getTime()) -
RegExp→new RegExp(obj.source, obj.flags) -
Map/Set→ 先构造空实例,再遍历.forEach或.entries()逐项添加 - 函数、DOM 节点、Canvas 上下文等——明确跳过或抛警告,不强行克隆
-
图表配置的实用建议
实际开发中,不必“全量深拷贝”整个配置对象:
- 多数场景只需克隆数据部分(如
option.series、option.xAxis.data),可用structuredClone(option.series)局部处理 - 函数字段(
tooltip.formatter、series.encode)通常无需克隆,保留原引用更安全 - ECharts / Chart.js 等库本身提供
setOption({ ... }, true)或merge方法,可替代手动克隆做增量更新 - 若配置来自服务端 JSON,本身不含函数/undefined,
JSON.parse(JSON.stringify())可临时用,但建议加校验:克隆后检查关键字段是否存在


















