object.hasown 直接查询对象内部属性描述符表,不走原型链、不调用可覆盖方法,兼容 object.create(null),无副作用,严格校验参数,性能优于 in 和 reflect.has。

Object.hasOwn 的底层实现不走原型链、不调用任何可被覆盖的方法,而是直接访问对象内部的属性描述符表(own property descriptor table),属于一次常数时间 O(1) 的底层结构查询。
绕过原型链与方法覆盖
它不依赖 Object.prototype.hasOwnProperty,也不通过 this 绑定或 call 调用。即使对象自身定义了 hasOwnProperty 属性,或 Object.prototype 被篡改,Object.hasOwn 仍能准确读取原始行为。
- 对 Object.create(null) 创建的对象完全兼容
- 不触发 getter、不执行用户逻辑、无副作用
- 不会因原型污染导致误判或报错
参数处理严格且轻量
入口处即校验第一个参数是否为对象:null 或 undefined 直接抛 TypeError;其他原始值(如字符串、数字)会被自动装箱为对象,但实际开发中应避免依赖该转换。
- Symbol 键必须传原始 Symbol 值,不能传字符串形式
- 不做隐式类型转换(例如不会把 'key' 自动转成 Symbol('key'))
- 所有判断都在引擎底层完成,无 JS 层循环或递归
与 in 和 Reflect.has 的本质区别
in 和 Reflect.has 都会沿原型链向上查找,而 Object.hasOwn 只查对象自身的 [[OwnPropertyKeys]] 列表,不访问任何祖先对象的内部结构。
- 查 toString 属性时:Object.hasOwn({}, 'toString') → false
- 同场景下 Reflect.has({}, 'toString') → true
- 这种隔离性让它成为属性归属判断的唯一可靠依据
现代引擎已深度优化
V8、SpiderMonkey 和 JavaScriptCore 均将其内联为接近寄存器级的操作,性能与 in 相当甚至略优——因为 in 还要递归遍历原型链。
- 不是语法糖,而是更底层、更干净的属性存在性断言
- 在 Chrome 93+、Firefox 97+、Safari 16.4+、Node.js 16.9+ 中原生支持
- polyfill 若仅用 call.bind 模拟,会带回原型污染风险,不推荐手写











