ESLint 把自定义 Object 改成 hasOwn 后报错,检查全局同名声明
script 模式下的 Object 可能是用户定义的全局变量。旧规则只确认它在全局作用域,自动修复却把自定义调用改成内置 API。
eslint --fix 把 Object.prototype.hasOwnProperty.call(...) 改成 Object.hasOwn(...),随后运行时报后者不是函数。若文件处于 script 模式,而且自己声明了名为 Object 的全局变量,先确认这不是内置构造函数。
ESLint 10.9.0 的明确触发形状如下,示例故意使用同名全局变量来说明边界:
let Object = {
prototype: {
hasOwnProperty: {
call() {},
},
},
};
Object.prototype.hasOwnProperty.call({}, 'foo');
它调用的是自定义对象的方法,并非内置的自有属性检查。prefer-object-has-own 旧实现只检查 Object 位于全局作用域,没有区分这份全局绑定是否有用户声明,因而给出不适用的自动替换。
先看绑定,再看拼写
保留实际 ESLint 版本、languageOptions.sourceType 和修复前后的代码。模块、函数内局部变量与 script 顶层声明的作用域不同,不能只搜索文件里有没有 Object 就断言命中同一个错误。
确认 identifier 指向自定义绑定后,恢复原调用。若这个变量名可以调整,可把自定义类型或工具对象改成具体名称,并同步所有引用;但改名需要按业务接口审查,不能只改声明不改调用,也不能把跨脚本共享名称悄悄替换。
反过来,若 Object 确实是内置构造函数,而目标运行时没有 ES2022 的 Object.hasOwn,应核对运行时支持和规则启用条件。那是另一条兼容性问题,不由“同名变量”解释。
10.13.0 会排除有定义的全局绑定
已核对的 ESLint 10.13.0 正式规则除了检查 global scope,还要求该变量的 defs.length === 0,以避免把用户定义的全局 Object 当成内置对象。项目允许时采用包含该判断的正式版,并检查编辑器和 CI 实际加载的版本。
不能更新时,对受影响文件暂停这条规则的自动修复,或在项目允许的范围内为具体调用加限定豁免;其他规则继续保留。不要实现一个假的 hasOwn 方法,只为迎合已经错误的 fix,那会把工具输出转成新的业务 API。
自动修复已经写入文件时,升级只会防止后续误改,不会自动恢复旧调用。先审查已有 diff,再沿真实业务入口检查自定义方法仍被调用,参数与副作用未变。
对照检查两种 Object
在原 script 配置下,保留一个自定义全局 Object 的例子,确认它不再被错误报告和改写;再保留一个确实使用内置 Object 的例子,确认符合规则条件时仍可得到合法 hasOwn 建议。只把整个规则关闭后看到 lint 通过,没有证明作用域判断已经恢复。
回退时恢复 ESLint 锁文件与临时规则范围,避免编辑器继续使用另一份全局安装。若原文件依赖多个脚本共享绑定,验证也应保留加载顺序;把文件临时切成 module 可能改变可见性,不能只为绕过规则而修改执行模型。


