json.stringify仅序列化字符串、数字、布尔值、null、数组和纯对象,自动忽略函数、undefined、symbol、不可枚举属性及原型属性,循环引用则报错;可控排除需预处理,如定义tojson方法或设enumerable为false。

JSON 方法本身不支持“识别并排除不可序列化属性”——它只会静默跳过那些无法序列化的值,比如函数、undefined、Symbol、循环引用等。真正能被 JSON.stringify() 处理的,仅限于字符串、数字、布尔值、null、数组和纯对象(且所有键必须是字符串)。所谓“排除”,其实是这些值根本进不了序列化流程,不是你主动过滤的结果。
哪些属性会被 JSON.stringify 自动忽略?
不是所有“不可见”或“特殊”的属性都会被跳过,关键看它是否满足 JSON 的数据模型约束:
- 函数、undefined、Symbol 类型的值:直接被丢弃(连键名都不出现)
-
不可枚举属性(enumerable: false):
JSON.stringify()只遍历可枚举自有属性,所以天然跳过 - 原型链上的属性:不会被访问,只处理对象自身的可枚举属性
-
循环引用:抛出
TypeError,不是忽略,而是中断
如何让某些属性“不出现在 JSON 字符串里”?
这不是靠“识别”,而是靠提前干预。主流做法有两种,都发生在序列化前:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
-
定义
toJSON()方法:该方法返回的对象,就是最终被序列化的结构。你可以在里面手动剔除敏感字段(如 password)、重命名或格式化值 -
用
Object.defineProperty设置enumerable: false:这样属性就不会被JSON.stringify()遍历到,效果等同于“排除”。注意:这不改变属性值本身,只是让它对遍历不可见
为什么不能靠 JSON.stringify 检测“不可序列化”?
它没有提供回调或钩子来告诉你“这里有个函数被跳过了”。它的设计就是“尽力而为”——遇到无法表示的值,要么静默丢弃(如 undefined),要么报错(如循环引用)。想做精细控制,就得在调用前自己检查:
- 遍历
Object.getOwnPropertyNames(obj)+Object.getOwnPropertyDescriptor(),查类型和描述符 - 对每个值用
typeof和Object.prototype.toString.call()判断是否为函数、Symbol、BigInt 等 - 但这类检查成本高,一般只在调试或工具库中使用,生产环境更推荐用
toJSON或预处理逻辑
替代方案:需要真正可控的深拷贝?
如果目标是“保留不可枚举属性”或“排除特定字段”,JSON.stringify() → parse() 就不合适了。应换用:
- fast-copy + strict: true:能完整复刻属性描述符,包括不可枚举、getter/setter
- Lodash _.cloneDeepWith:允许传入自定义克隆逻辑,可跳过指定键或类型
- 手写递归 + getOwnPropertyDescriptors:完全掌控每个属性的拷贝行为










