JSON.parse(JSON.stringify())将NaN转为null,因JSON标准不支持NaN;可用structuredClone、自定义序列化或lodash.cloneDeep解决。

JavaScript 中用 JSON.parse(JSON.stringify()) 做深拷贝时,NaN 会被静默转成 null,这是 JSON 标准本身的行为——NaN 不是合法的 JSON 值,序列化时被替换为 null。
为什么 NaN 会变成 null
JSON 规范只支持 null、布尔值、数字(含整数和浮点)、字符串、数组、对象这六种原始类型。NaN、Infinity、-Infinity、undefined、函数、Symbol、Date、RegExp 等都不在其中。调用 JSON.stringify(NaN) 直接返回 "null",所以后续 JSON.parse 就得到 null。
想保留 NaN,就不能依赖原生 JSON 方法
若业务逻辑中 NaN 有语义(比如表示“缺失的数值”且需与 null 区分),必须绕过 JSON 序列化。推荐以下方式:
-
用结构化克隆(现代浏览器 & Node.js 17+):
structuredClone(obj)原生支持NaN、Infinity、Date、Map、Set等,且保留类型。它是标准方案,最可靠。 -
自定义序列化 + 反序列化:在
JSON.stringify的replacer中把NaN替换成特殊标记(如"__NaN__"),再在JSON.parse的reviver中还原。注意要避免污染正常字符串。 -
用成熟库(如 lodash):
_.cloneDeep(obj)内部不走 JSON,能正确处理NaN、正则、日期等,适合兼容性要求高的项目。
手动处理 NaN 的 JSON 拷贝示例
如果坚持用 JSON 流程并想修复 NaN,可这样写:
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
立即学习“Java免费学习笔记(深入)”;
function jsonCloneWithNaN(obj) {
const nanMarker = '__JSON_NAN__';
const str = JSON.stringify(obj, (key, value) => {
return Number.isNaN(value) ? nanMarker : value;
});
return JSON.parse(str, (key, value) => {
return value === nanMarker ? NaN : value;
});
}
// 使用
const original = { a: 1, b: NaN, c: [2, NaN] };
const cloned = jsonCloneWithNaN(original);
console.log(cloned.b); // NaN(不是 null)
console.log(cloned.c[1]); // NaN
⚠️ 注意:该方法仅解决 NaN,对 Infinity、undefined、函数等仍无效,且标记字符串若恰好出现在原始数据中会导致误判。
更稳妥的做法是明确需求边界
先确认是否真需要深拷贝,还是只需浅拷贝或不可变更新;再判断数据结构是否复杂。简单纯对象数组用 structuredClone 最省心;老环境用 lodash.cloneDeep 更稳;若只是临时处理少量 NaN 字段,也可在拷贝后单独遍历修复,比改序列化逻辑更清晰。

















