hasOwnProperty 是判断属性是否为对象自身的最直接方法,但必须用 Object.prototype.hasOwnProperty.call(obj, key) 防止被覆盖;Object.keys() 更安全简洁,仅返回自身可枚举属性。

要准确判断一个属性是否属于对象自身(而非继承自原型链),hasOwnProperty 是最直接、语义最清晰的工具,但它的使用有明确边界和潜在陷阱。写法看似简单,实际容易出错——尤其在健壮性、兼容性和可维护性层面。
必须用 Object.prototype.hasOwnProperty.call
不能直接调用 obj.hasOwnProperty(key),因为对象可能覆盖该方法:
- 如果 obj 自身定义了
hasOwnProperty: () => false,直接调用会永远返回 false - 正确做法是借用原生方法:
Object.prototype.hasOwnProperty.call(obj, key) - 这是防御性编程的标配,适用于所有不确定来源的对象(如用户输入、第三方库返回值)
遍历自身属性时优先用 Object.keys()
for…in + hasOwnProperty 组合虽经典,但现代代码应倾向更简洁安全的方式:
-
Object.keys(obj)天然只返回对象自身的可枚举属性,无需手动过滤 - 配合
forEach或map更函数式、更少出错:Object.keys(obj).forEach(key => console.log(key, obj[key])) - 注意:Object.keys 不包含 Symbol 属性或不可枚举属性;如需完整自有属性,用
Object.getOwnPropertyNames(obj)或Reflect.ownKeys(obj)
区分“属性存在”与“属性有值”
hasOwnProperty 只回答“这个键是不是对象自己声明的”,不管值是什么:
立即学习“Java免费学习笔记(深入)”;
-
{ a: undefined }.hasOwnProperty('a')→ true -
{ a: null }.hasOwnProperty('a')→ true - 若想判断“属性是否存在且不为 null/undefined”,需额外检查:
obj.hasOwnProperty(key) && obj[key] !== undefined - 避免误把
obj.key !== undefined当作“自有属性判断”,它无法区分继承属性和自身 undefined 值
避免在原型上污染或覆盖
全局原型修改会破坏 hasOwnProperty 的行为基础:
- 禁止给
Object.prototype添加属性(如Object.prototype.customMethod = …),否则所有对象的 for…in 都会遍历到它,且 hasOwnProperty 无法屏蔽 - 若必须扩展,用
Object.defineProperty并设enumerable: false - 构造函数中慎用
this.hasOwnProperty = …,极易引发后续逻辑失效


















