object.prototype.hasownproperty仅判断属性是否为对象自身拥有,与属性描述符(如enumerable、writable、configurable、getter/setter)无关;无论属性是否可枚举、只读或不可配置,只要在对象自身上定义即返回true。

Object.prototype.hasOwnProperty 本身不依赖、也不读取属性描述符(descriptor),它只关心“这个属性是不是对象自身拥有的”,和该属性是否可枚举、是否可写、是否有 getter/setter 等描述符细节完全无关。
hasOwnProperty 只看“归属”,不看“配置”
它判断的是:指定的属性名(字符串或 Symbol)是否作为自有属性存在于目标对象上,即是否直接定义在该对象自身,而非从原型链继承而来。无论这个属性是通过字面量、Object.defineProperty、还是赋值语句添加的,只要它在对象自身上,hasOwnProperty 就返回 true。
- 即使属性被设为
enumerable: false(不可枚举),hasOwnProperty仍返回true - 即使属性是只读的(
writable: false)或不可配置(configurable: false),也照样返回true - 哪怕属性是个 getter 或 setter(访问器属性),只要它在对象自身上定义,
hasOwnProperty依然认它
描述符影响的是“如何访问/修改”,不是“是否存在”
Object.defineProperty 设置的描述符(如 value、get、set、enumerable、writable、configurable)决定了属性的行为和可见性,但不会改变它“属于这个对象”的事实。换句话说:
-
hasOwnProperty的结果不受enumerable影响 —— 不可枚举属性仍是自有属性 -
hasOwnProperty的结果不受writable或configurable影响 —— 它们控制的是后续操作权限,不是存在性 - 你可以用
Object.getOwnPropertyDescriptor(obj, key)查看某个自有属性的完整描述符,但hasOwnProperty本身不做这件事
一个典型对比场景
假设你这样定义对象:
const obj = {};
Object.defineProperty(obj, 'hidden', {
value: 42,
enumerable: false,
writable: false,
configurable: false
});
此时:
-
obj.hasOwnProperty('hidden')→true(它是 obj 自身的属性) -
for...in obj遍历不到hidden(因为enumerable: false) -
Object.keys(obj)也返回空数组(keys只返回可枚举自有属性) -
Object.getOwnPropertyNames(obj)会包含'hidden'(它列出所有自有属性,不管是否可枚举)
注意覆盖风险:hasOwnProperty 本身也可能被改写
虽然 hasOwnProperty 是原型方法,但它不是只读的 —— 如果你在对象上直接定义同名属性(比如 { hasOwnProperty: () => false }),就会遮蔽原型上的方法。这时调用 obj.hasOwnProperty('x') 实际执行的是你自定义的函数,不再反映真实归属关系。
安全做法是绕过实例,直接用原型方法:
Object.prototype.hasOwnProperty.call(obj, 'key')- 或者更简洁:
{}.hasOwnProperty.call(obj, 'key')
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











