in 检查原型链上是否存在键,hasOwnProperty 和 Object.hasOwn 仅检查实例自身属性;Object.hasOwn 更安全,推荐用于属性存在性判断。

在类实例中,in 和 hasOwnProperty 的行为差异依然由“是否查原型链”决定——in 会命中类原型上的方法和继承属性,hasOwnProperty 只认实例自身显式设置的属性。
in 会把类原型上的方法和字段都算作“存在”
类定义中写在 prototype 上的内容(包括方法、getter、以及通过 Object.defineProperty 添加的可枚举/不可枚举属性),只要可访问,in 就返回 true:
- 构造函数内用
this.xxx = ...设置的属性 →in返回true - 类体中定义的方法(如
sayHi() {})→in返回true(因为挂载在原型上) - 父类原型上的方法(
class B extends A中A.prototype.getName)→in仍返回true - 即使属性值是
undefined或null,只要键名在原型链某处声明过,in就为true
hasOwnProperty 只响应实例自身的属性
它完全无视类或父类原型上的任何东西,只看该实例对象内部的属性表:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
-
this.name = 'Alice'→obj.hasOwnProperty('name')为true -
obj.sayHi()是从MyClass.prototype继承来的 →obj.hasOwnProperty('sayHi')为false - 用
Object.defineProperty(obj, 'hidden', { value: 42, enumerable: false })直接加到实例上 →hasOwnProperty('hidden')仍为true(哪怕不可枚举) - 若实例是
Object.create(null)创建的(无原型),直接调用obj.hasOwnProperty会报错;应改用Object.prototype.hasOwnProperty.call(obj, key)
现代推荐:优先用 Object.hasOwn 替代 hasOwnProperty
它语义更清晰、调用更安全,且不依赖原型链:
立即学习“Java免费学习笔记(深入)”;
-
Object.hasOwn(obj, 'name')等价于Object.prototype.hasOwnProperty.call(obj, 'name') - 不会因
obj.hasOwnProperty = null这类污染而失效 - Node.js 16.9+、Chrome 93+、Firefox 91+ 均原生支持;旧环境可用 polyfill 回退
- 在遍历类实例时做属性过滤(如
for (const k in obj) { if (Object.hasOwn(obj, k)) { ... } }),是最稳妥的做法
典型误用场景与规避方式
常见问题不是“哪个错了”,而是没按意图选对工具:
- 想确认实例有没有某个配置字段(比如
obj.timeout)→ 用Object.hasOwn(obj, 'timeout') - 想判断实例能否调用某个方法(比如
obj.toJSON)→ 用'toJSON' in obj更合理(关心的是“能不能用”,不是“谁定义的”) - 在
for...in循环中漏掉hasOwn或Object.hasOwn守门 → 会把toString、constructor等原型方法也遍历进来 - 用
obj.prop !== undefined判断存在性 → 若prop显式设为undefined,结果为false,逻辑错误

















