应优先使用 Object.hasOwn(obj, 'prop') 检查对象自有属性,它比 in 更精准、比 hasOwnProperty() 更安全;in 会遍历整个原型链导致误判,而 Object.hasOwn 只检测自身属性且不被覆盖。

使用 in 操作符检查属性时,它会查找**整个原型链**上的可枚举和不可枚举属性(包括继承属性),这常导致误判——你以为在检查对象自有属性,实际却命中了原型上的属性。防御性代码的关键是明确区分“自有属性”和“继承属性”,并按需选择正确工具。
用 hasOwnProperty() 替代 in 判断自有属性
in 无法区分属性来源,而 Object.prototype.hasOwnProperty() 只检测对象自身是否声明了该属性,不查原型链。这是最直接的替代方案。
- 推荐写法:
obj.hasOwnProperty('prop') - 注意:若对象可能覆盖了
hasOwnProperty(如{ hasOwnProperty: null }),应通过Object.prototype.hasOwnProperty.call(obj, 'prop')安全调用 - ES2022 引入
Object.hasOwn(obj, 'prop'),更简洁且无需担心被覆盖,建议优先使用
明确意图:用 in 还是 hasOwnProperty?
不要默认用 in 做存在性检查。先问自己:你关心的是“这个键是否存在(无论在哪)”,还是“这个对象自己有没有定义它?”
- 需要检查继承属性(例如判断是否支持某个方法)→ 用
'method' in obj - 需要确认配置项、数据字段是否由当前对象显式设置 → 用
Object.hasOwn(obj, 'key') - 遍历对象时过滤掉继承属性 → 配合
for...in使用hasOwn做守卫
避免污染原型,从源头减少混淆
很多继承属性问题源于在 Object.prototype 或构造函数原型上意外添加属性。这类全局污染会让所有对象都“拥有”不该有的属性。
- 禁止向
Object.prototype添加属性(如Object.prototype.customMethod = ...) - 扩展内置原型时,用
Object.defineProperty并设enumerable: false,降低被in和for...in捕获的概率 - 使用类或
Object.create(null)创建无原型的对象(如字典、配置缓存),彻底规避继承干扰
类型安全增强:结合 typeof 和 undefined 检查
仅检查属性存在还不够。有些属性存在但值为 undefined 或 null,业务逻辑可能需要进一步验证。
- 存在且有有效值:
Object.hasOwn(obj, 'prop') && obj.prop !== undefined - 存在且为函数:
Object.hasOwn(obj, 'fn') && typeof obj.fn === 'function' - 对可能为
null的对象,先做真值判断再访问:obj && Object.hasOwn(obj, 'x') ? obj.x : defaultValue


















