hasOwnProperty 是 JavaScript 中判断属性是否为对象自身属性的最直接方法,只检测对象自有属性表,忽略原型链继承属性,适用于安全遍历、配置校验和序列化过滤等场景。

hasOwnProperty 是 JavaScript 中判断属性是否属于对象“自身”的最直接方法——它只认对象自己身上明确定义的属性,对原型链上继承来的属性一律无视。
为什么需要区分“自身”和“原型”
JavaScript 的属性查找机制默认会沿着原型链向上找:访问 obj.name 时,如果 obj 自己没有 name,引擎会自动去 obj.__proto__、再往上 __proto__.__proto__,直到 Object.prototype 为止。这种机制带来复用便利,但也容易造成混淆:
- 用
for...in遍历对象时,会把原型上的方法(如sayHello、toString)一并列出 - 检查某个键是否存在时,
'toString' in obj返回true,但你可能只关心对象自己有没有这个字段
hasOwnProperty 的工作方式
它不查原型链,只看对象内部的自有属性表(own property table)。只要属性是通过以下方式直接加到该对象上的,就返回 true:
obj.key = valueobj['key'] = valueObject.defineProperty(obj, 'key', {...})- 构造函数中
this.key = value
而以下情况一律返回 false:
立即学习“Java免费学习笔记(深入)”;
- 属性来自
obj.__proto__(比如Person.prototype.sayHello) - 属性来自
Object.prototype.toString或valueOf - 属性名拼写错误或根本不存在
典型使用场景
避免原型污染带来的误判:
- 安全遍历对象自有属性:
for (let key in obj) { if (obj.hasOwnProperty(key)) { /* 处理 key */ } } - 校验配置对象是否包含某字段:
if (config.hasOwnProperty('timeout')) { use(config.timeout); } - 深拷贝或序列化前过滤掉继承方法,防止意外执行:
JSON.stringify(Object.keys(obj).filter(k => obj.hasOwnProperty(k)).reduce((o, k) => ({...o, [k]: obj[k]}), {}))
注意边界情况
它不是万能的,需留意几点:
- 不能检测不可枚举属性(
enumerable: false的属性仍会被识别,只要它是自身的) - 对
Object.create(null)创建的对象无效(因为没继承Object.prototype),需改用Object.prototype.hasOwnProperty.call(obj, 'key') - 不处理 Symbol 属性?错——它支持 Symbol 类型参数:
obj.hasOwnProperty(Symbol('id'))


















