JSON.parse() 抛 SyntaxError(如非法字符或截断),必须用 try...catch 捕获;JSON.stringify() 遇循环引用报 TypeError,undefined/function/Symbol 被静默丢弃,BigInt 需自定义 replacer 处理。

直接用 JSON.parse() 和 JSON.stringify() 是安全且高效的,前提是数据来源可信、结构可控;若涉及用户输入或嵌套过深,必须加校验与限制。
JSON.parse() 会抛什么错?怎么捕获才不崩
常见错误是 SyntaxError: Unexpected token(非法字符)或 Unexpected end of JSON input(截断数据)。这些错误无法被 try...catch 外部静默吞掉——必须显式包裹。
- 永远对不可信输入(如
localStorage.getItem('data')、fetch响应体)做try...catch - 不要依赖
typeof data === 'object'判断解析成功,null也是object - 可加一层类型守卫:解析后检查
result && typeof result === 'object' && !Array.isArray(result)(若预期是对象)
try {
const data = JSON.parse(input);
if (data && typeof data === 'object' && !Array.isArray(data)) {
return data;
}
} catch (e) {
console.warn('Invalid JSON:', e.message);
return null;
}
JSON.stringify() 的循环引用与特殊值怎么处理
遇到 TypeError: Converting circular structure to JSON 就说明对象里有循环引用(比如 a.b = a);而 undefined、function、Symbol 会被静默丢弃,Date 变成字符串,BigInt 直接报错。
- 用
replacer参数过滤掉不合法字段:JSON.stringify(obj, (key, val) => typeof val === 'function' ? undefined : val) - 处理循环引用推荐用第三方库(如
flatted),自己实现需维护seenSet 记录已遍历对象 -
BigInt必须显式转为字符串或数字:JSON.stringify(obj, (k, v) => typeof v === 'bigint' ? v.toString() : v)
大数据量 JSON 解析/生成卡顿?别硬扛
JSON.parse() 是同步阻塞操作,10MB 以上 JSON 在主线程解析可能卡死 UI;JSON.stringify() 对深层嵌套或超大数组也会显著拖慢。
立即学习“Java免费学习笔记(深入)”;
-
前端解析大文件时,优先用
Web Worker搬到后台线程:worker.postMessage({ type: 'parse', data: jsonString }) - 避免无意义深拷贝:
JSON.parse(JSON.stringify(obj))看似简单,但会丢失原型、方法、Date实例等,且性能极差;改用structuredClone()(现代浏览器)或专用克隆库 - 服务端返回前就做精简:用
select字段控制、分页、压缩(gzip)比前端硬解析更有效
为什么不能用 eval() 或 new Function() 代替 JSON.parse()
因为它们执行任意代码,只要 JSON 字符串里混入 "}; alert(1); {" 这类 payload,就会触发 XSS。哪怕加了正则过滤,也防不住 Unicode 编码绕过、换行符干扰等边缘 case。
-
JSON.parse()是原生语法解析器,只认标准 JSON 格式,不执行任何 JS 表达式 - 某些老项目用
eval('(' + str + ')'),这和把门钥匙交给陌生人没区别 - 若真要解析非标准格式(如带注释、单引号),用专用 parser(如
json5),而非降级到eval
最常被忽略的其实是缓存策略:反复解析同一段 JSON 字符串时,别每次都调用 JSON.parse();解析结果可按内容哈希缓存,但要注意对象引用是否会被意外修改。











