object.hasown 是 es2022 引入的安全属性检测方法,现代浏览器及 node.js 16.9+ 原生支持;老旧环境需用 object.prototype.hasownproperty.call(object(obj), prop) 降级,禁用 obj.hasownproperty。

Object.hasOwn 是 ES2022 正式引入的静态方法,现代环境已广泛支持,但低版本浏览器(如 Safari 15.3 及更早、Firefox 91 及更早、IE 全系、部分旧版 Android WebView)不支持。兼容性策略需兼顾安全性、简洁性和运行环境,不能只看“能不能用”,更要考虑“用得安不安全”。
优先在支持环境中直接使用
Chrome 93+、Firefox 92+、Safari 15.4+、Edge 93+ 和 Node.js 16.9+ 均原生支持 Object.hasOwn,无需 polyfill。新项目或明确限定运行环境的场景(如内部管理后台、新版 App 内嵌 WebView),应直接采用:
-
统一写法:始终用
Object.hasOwn(obj, key),避免混用obj.hasOwnProperty -
禁用不安全调用:通过 ESLint 规则
no-prototype-builtins自动拦截obj.hasOwnProperty的使用 -
TypeScript 项目:确保
lib配置包含es2022或更高版本,获得类型提示与编译检查
对老旧环境做安全降级
当必须兼容 Safari 15.3、Node.js 16.0–16.8 或 IE 时,不能简单回退到 obj.hasOwnProperty(key) —— 它仍受原型污染和 null/undefined 输入影响。应采用真正健壮的降级方案:
-
推荐 polyfill:使用 MDN 官方轻量实现,或手动定义:
Object.hasOwn ??= (obj, prop) => Object.prototype.hasOwnProperty.call(Object(obj), prop); -
关键点:
Object(obj)确保 null/undefined 不报错;call绕过对象自身方法被覆盖的风险 -
不推荐写法:
Object.hasOwn = Object.prototype.hasOwnProperty(丢失 this 绑定)、obj?.hasOwnProperty?.(key)(仍触发污染后的原型方法)
构建工具自动适配
在 Next.js、Vite 或 Webpack 项目中,无需手动维护 polyfill:
-
Babel:配合
@babel/preset-env并配置目标浏览器(如"supports": { "chrome": "90" }),可自动注入兼容代码 - Next.js:升级至 v13.4+ 后,默认启用 modern & legacy 构建输出,会按用户 UA 分发适配版本
-
注意:避免在全局 prototype 上扩展(如给
Object.prototype加hasOwn方法),这在 Safari 旧版中可能引发枚举异常
哪些场景绝不能妥协
以下逻辑一旦出错,可能引发权限绕过、配置失效或数据误处理,必须强制使用 Object.hasOwn 或其安全降级:
- 用户输入字段白名单校验(如
if (Object.hasOwn(data, 'role'))) - 配置对象缺失兜底(如
config.timeout ??= 5000前先确认 key 是否存在) - 序列化前过滤不可信属性(配合
for...in时显式用Object.hasOwn判断) - 框架层对第三方传入对象的自有属性断言(如 React 组件 props 校验)











