Object.hasOwn(obj, key) 能彻底避开原型链被篡改风险,因其不依赖对象自身的hasOwnProperty方法或原型链,直接检查对象自身属性描述符,兼容null原型对象且不受方法重写影响。
直接用 Object.hasOwn(obj, key) 替代 obj.hasOwnProperty(key),就能彻底避开原型链被篡改的风险——它不依赖对象自身的 hasOwnProperty 方法,也不访问原型,只检查对象自身是否定义了该属性。
因为 hasOwnProperty 是从 Object.prototype 继承来的方法,一旦对象自己重写了这个方法,或原型链被污染,检测就失效:
hasOwnProperty: () => false,导致真实存在的属性被误判为不存在Object.create(null) 创建的对象,根本没有 hasOwnProperty 方法,调用直接报错它专为解决上述问题而设计,是 ES2022 正式引入的推荐方案:
Object.prototype
Object.create(null) 创建的对象也能安全调用hasOwnProperty,Object.hasOwn 结果依然准确旧写法(有风险):
obj.hasOwnProperty('name') // ❌ 可能被重写、可能报错
新写法(推荐):
Object.hasOwn(obj, 'name') // ✅ 安全、简洁、语义明确
遇到需要兼容老环境的场景,可降级为:
Object.prototype.hasOwnProperty.call(obj, 'name')
但注意:这仍需确保 Object.prototype.hasOwnProperty 未被篡改,且写法更冗长。
几个容易忽略但关键的点:
undefined、null 还是其他任何值,只要键在对象自身上,就返回 true
Object.hasOwn(arr, '2') 检查索引 2 是否被显式设置(而非仅因数组长度而“存在”)Object.hasOwn(obj, mySym),不能写成 'mySym'