应优先使用 object.hasown(obj, key) 检查自有属性,因其不依赖原型链、语义精准、性能优且兼容性好;需检查可访问性(含继承)时用 'key' in obj;对 map/set/array/proxy 等特殊结构须选用对应原生 api;禁用 obj.prop !== undefined、obj.hasownproperty('key') 等高危写法。

在编写高级库时,属性存在性检查不是“怎么写更短”,而是“怎么写更稳、更可预期”——因为你的代码会被千百种对象调用,包括 Object.create(null)、被 Proxy 封装的对象、原型被篡改的第三方实例,甚至自定义 hasOwnProperty 方法的对象。
优先用 Object.hasOwn() 检查自有属性
现代库应默认使用 Object.hasOwn(obj, key) 判断对象是否**自身定义**了某个属性:
- 它不依赖对象原型链,
Object.create(null)或obj.hasOwnProperty = null下仍能正常工作 - 语义精准:只回答“这个 key 是不是 obj 自己的”,不混入
toString、toJSON等继承/内置属性 - 性能优于
Object.keys().includes(),也不触发 getter(而obj[key]可能触发) - 主流环境已全覆盖(Node.js 16.9+、Chrome 93+、Firefox 92+、Safari 16.4+);旧环境可用一行 polyfill 回退:
Object.hasOwn ??= Object.prototype.hasOwnProperty.call;
用 'key' in obj 检查可访问性(含继承)
当你真正关心的是“调用 obj.key 是否安全、是否会 fallback 到原型方法”,就该用 'key' in obj:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 它是语法级操作符,无函数调用开销,引擎深度优化
- 覆盖不可枚举属性(如
obj[Symbol.iterator]、obj.toJSON),也覆盖原型链(toString、valueOf) - 不会读取属性值,因此不触发 getter、不引发副作用
- 兼容性极佳:从 ES1 就存在,IE6 都支持
对特殊结构,用对应原生 API
高级库常需处理非普通对象。别强行统一用 in 或 hasOwn,按类型选专用方法:
-
Map/WeakMap→ 用map.has(key)(支持任意键类型,语义唯一) -
Set/WeakSet→ 用set.has(value) -
Array→ 稀疏数组慎用in(1 in [,,2]是true但索引 1 为空),优先用array.length > index或array.hasOwnProperty(index) -
Proxy对象 → 若需拦截检测逻辑,用Reflect.has(target, key),它与in行为一致且天然兼容 trap
明确禁用的写法
这些看似简洁的写法,在库中属于高危模式,必须杜绝:
-
obj.prop !== undefined:属性存在但值为undefined时误判;obj为null/undefined时直接抛错 -
obj.hasOwnProperty('key'):一旦对象自身重写了该方法(哪怕只是赋值obj.hasOwnProperty = void 0),就崩溃 -
Object.keys(obj).includes('key'):漏掉不可枚举属性(JSON.stringify依赖的toJSON就会失效)、忽略原型链、每次生成新数组造成 GC 压力 -
if (obj.prop):把0、false、''、null全部当“不存在”,语义完全错位
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










