为何看似有属性的对象JSON.stringify返回空对象且hasOwnProperty返回false
问题原因与解决方案
1. 首要错误:hasOwnProperty调用方式错误
hasOwnProperty方法必须传入要检测的属性名称作为入参,空参数调用时会默认传入undefined,永远返回false,不属于对象本身的问题。
正确调用示例:要检测对象是否存在自身属性zh,需写成test.hasOwnProperty('zh')。
2. JSON.stringify返回空对象的核心原因
JSON.stringify仅会序列化对象自身的、可枚举的属性,你在控制台看到的属性不属于该范围,常见情况如下:
- 属性挂载在对象的原型链上,不属于对象自身属性
- 属性是对象的不可枚举属性(
enumerable描述符为false) - 控制台展示的是对象引用的实时值:你执行
console.log(test)时对象还没有对应属性,后续代码赋值后你才展开控制台的对象,此时展示的是赋值后的结果,属于控制台的延迟读取特性,不是执行stringify那一刻的对象状态。
3. 排查代码示例
const test = action.data.displayNameLocalization; // 打印对象执行stringify那一刻的快照,排除控制台延迟读取干扰 console.log('执行stringify时的对象快照:', JSON.parse(JSON.stringify(test))); // 查看对象所有自身属性(包含不可枚举) console.log('自身所有属性:', Object.getOwnPropertyNames(test)); // 查看所有自身属性的可枚举状态 console.log('属性描述符:', Object.getOwnPropertyDescriptors(test)); // 查看原型链上的属性 console.log('原型链属性:', Object.getOwnPropertyNames(Object.getPrototypeOf(test))); // 正确检测指定属性是否为自身属性 console.log('是否存在自身zh属性:', test.hasOwnProperty('zh'));
4. 常见场景修复方案
- 如果是原型链属性:将属性复制到对象自身,例如
const newObj = {...test},再对newObj执行stringify - 如果是不可枚举属性:手动指定要序列化的属性,或者使用
Object.defineProperty修改属性的enumerable为true - 如果是异步赋值延迟:保证在对象属性赋值完成后再执行序列化操作
内容的提问来源于stack exchange,提问作者Zenixo
相关产品推荐
相关产品推荐

