判断对象属性是否为自身定义,应优先使用 object.hasown(obj, key);若需兼容旧环境,则用 object.prototype.hasownproperty.call(obj, key);禁用 'in' 和值判断,因其无法准确区分自有属性与原型链属性。

判断对象属性是否为自身定义,核心是绕过原型链、避开被篡改的方法,只看对象“自己写进去”的那些键。
优先用 Object.hasOwn() —— 现代标准的首选
ES2022 引入的 Object.hasOwn(obj, key) 是目前最直接、最安全的方式:
- 不依赖对象自身的任何方法,哪怕 obj 是
Object.create(null)或hasOwnProperty被删/重写,也能正常工作 - 语义清晰:只检测自有属性(own property),不查原型链,也不受
enumerable影响 - 性能优于
Object.keys().includes(),且不生成临时数组 - Chrome 93+、Firefox 91+、Safari 16.4+、Node.js 16.9+ 已原生支持
兼容老环境时,固定调用原始 hasOwnProperty
如果需支持 IE 或早期运行时,绝不能写 obj.hasOwnProperty('key'),而应使用:
-
Object.prototype.hasOwnProperty.call(obj, 'key')—— 绑定原始方法,跳过对象自己的查找路径 - 或简写为
({}).hasOwnProperty.call(obj, 'key'),效果一致 - 即使 obj 的
hasOwnProperty被赋值为字符串、函数或undefined,也不会报错
别用 in 和值判断来代替自有属性检测
'key' in obj 和 obj.key !== undefined 都不是正确解法:
-
in沿整个原型链查找,一旦Object.prototype.key = true被注入,'key' in {}就会返回true,造成误判 -
obj.key !== undefined本质是值判断:属性存在但值为undefined→ 判定为“不存在”;属性有 getter → 可能触发副作用甚至抛错 - 它们的语义和目标不匹配:你要的是“这个键是不是对象自己定义的”,不是“能不能访问到”或“值是不是未定义”
补充说明:其他自有属性枚举方法的定位
Object.getOwnPropertyNames() 和 Reflect.ownKeys() 不是存在性检测工具,而是枚举工具:
-
Object.getOwnPropertyNames(obj)返回所有自有属性名(含不可枚举) -
Reflect.ownKeys(obj)还额外包含 Symbol 属性 - 若仅需判断单个属性是否存在,用它们再配合
.includes()属于低效兜底,不如直接用Object.hasOwn或Object.prototype.hasOwnProperty.call
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











