有必要,而且在多数现代项目中已是推荐实践——object.hasown 能规避原型链污染、无原型对象、全局篡改三类风险,替代成本低且收益明确。

有必要,而且在多数现代项目中已是推荐实践。核心原因不是“功能更强”,而是“更可靠”——hasOwnProperty 本质依赖原型链,而原型链可能被污染、覆盖或缺失;Object.hasOwn 则绕过原型链,直接调用原始实现,从设计上规避了三类典型风险。
对象自身重写了 hasOwnProperty 方法
这是最常见也最容易被忽略的问题。只要对象显式定义了同名属性,调用就会失效:
-
危险写法:
const user = { hasOwnProperty: () => false, name: 'Alice' }; user.hasOwnProperty('name') // 返回 false(错误) -
安全写法:
Object.hasOwn(user, 'name') // 返回 true(正确)
这类情况常出现在反序列化 JSON 后的对象、第三方 SDK 返回的数据、或用户动态构造的配置对象中。
对象没有原型(如 Object.create(null))
很多工具库、Map 转换结果、或刻意隔离原型的场景会创建无原型对象:
-
危险写法:
const data = Object.create(null); data.id = 1; data.hasOwnProperty('id') // TypeError: data.hasOwnProperty is not a function -
安全写法:
Object.hasOwn(data, 'id') // true(直接可用)
你无法预判所有传入对象是否继承自 Object.prototype,但 Object.hasOwn 对这类对象天然兼容。
Object.prototype 被全局篡改
虽然不推荐,但在老旧系统、调试工具、或恶意注入场景中,Object.prototype.hasOwnProperty = null 或 = () => true 确实发生过。此时:
- 所有
obj.hasOwnProperty()调用都会返回错误结果或抛错 -
Object.hasOwn(obj, key)不读取Object.prototype上的任何内容,完全不受影响
这不是理论漏洞,而是真实出现在 SSRF 防御绕过、模板引擎沙箱逃逸等安全事件中的环节。
替代成本低,收益明确
迁移几乎零成本:
- 参数顺序一致:
obj.hasOwnProperty('x')→Object.hasOwn(obj, 'x') - 返回值语义相同:都是布尔值,且只检查自有属性(不查原型链)
- 现代环境已全面支持:Chrome 93+、Firefox 92+、Safari 15.4+、Node.js 16.9+
- TypeScript 类型更精确:
(obj: unknown, prop: PropertyKey) => boolean,避免any泛滥
若需兼容旧环境,可用一行 polyfill:Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty),比手写兜底更简洁、更健壮。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











