object.hasown(obj, prop)是es2022引入的静态方法,彻底绕过原型链污染,不依赖object.prototype,直接调用原始hasownproperty实现,安全检测对象自身属性;支持symbol(需传原始值)、对null/undefined抛typeerror,chrome 93+等现代环境原生支持。

直接用 Object.hasOwn(obj, prop) 替代 obj.hasOwnProperty(prop),就能彻底绕过原型链被篡改的风险——它不读取对象的原型,也不调用任何可能被覆盖的方法,只检查对象自身是否定义了该属性。
为什么 hasOwnProperty 不再安全
hasOwnProperty 是挂载在 Object.prototype 上的实例方法。一旦原型被污染(比如 Object.prototype.hasOwnProperty = () => false),所有继承该原型的对象调用它都会返回错误结果或直接报错。更常见的情况是:
- 使用
Object.create(null)创建的对象,根本没这个方法,调用即TypeError - 某些第三方库或调试工具会悄悄重写它,导致权限校验、配置过滤等逻辑静默失效
- 对象自身定义了同名方法(如
{ hasOwnProperty: () => true }),覆盖原始行为
Object.hasOwn 的核心优势
它是 ES2022 正式引入的静态方法,内部直接调用原始、未被篡改的 hasOwnProperty 实现,完全不依赖目标对象的原型链:
- 对
null、undefined安全返回false,无需额外判空 - 支持
Object.create(null)对象,开箱即用 - 传入 Symbol 时必须用原始值(
Symbol("key")),不能传字符串描述 - 现代环境原生支持:Chrome 93+、Firefox 97+、Safari 16.4+、Node.js 16.9+
替换时要注意的关键细节
不是简单全局替换字符串,需关注实际行为差异:
-
第一个参数必须是对象类型:传
null或undefined会抛TypeError(注意:这是规范行为,不是 bug) -
Symbol 属性要传原始值:写成
Object.hasOwn(obj, "Symbol(key)")是错的;正确写法是先声明const sym = Symbol("key"),再传sym -
不再需要 .call 绑定:以前常用
Object.prototype.hasOwnProperty.call(obj, "x")做兜底,现在直接Object.hasOwn(obj, "x")更简洁可靠
哪些场景必须优先替换
以下逻辑一旦受原型污染就可能引发严重问题,应立即迁移到 Object.hasOwn:
- 用户输入 JSON 的白名单校验(如只允许
name、email字段) - 遍历
for...in时过滤原型属性(替代obj.hasOwnProperty(key)) - 序列化前判断某个配置项是否为自有属性(避免意外序列化继承方法)
- 与 Proxy、
Object.assign或 Map 转换后的对象交互时的属性存在性检查










