
全面解析 eslint-plugin-unicorn 的no-instanceof-builtins规则用更可靠的类型检查替代instanceof【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicornno-instanceof-builtins是 eslint-plugin-unicorn 中用于禁止对内置对象使用instanceof做类型判断的规则。本文围绕该规则的完整文档、选项配置与源码实现展开说明为何instanceof在内置对象上并不可靠、规则在loose与strict两种策略下各覆盖哪些构造函数以及哪些场景会被自动修复、哪些只能通过编辑器建议手动应用帮助你在项目中以更稳妥的类型检查方式落地这套规范。规则速览维度说明规则名称unicorn/no-instanceof-builtins规则类型problem问题类规则内置配置默认包含于recommended与unopinionated配置中可修复性支持--fix自动修复同时提供编辑器建议suggestion适用语言JS含 Vue 模板中的表达式声明位置rules/no-instanceof-builtins.js该规则在 readme.md 的规则总表中被标记为✅ ☑️即同时进入recommended与unopinionated配置、支持自动修复与编辑器建议。在 configs 目录的配置文件中它随recommended配置默认启用无需手动声明即可生效若你使用的是自定义扁平配置也可以单独开启。为什么不应该对内置对象使用instanceofJavaScript 的instanceof运算符检查的是某个对象的原型链上是否存在右侧构造函数的prototype对象它本质上依赖**同一个 JavaScript 运行环境realm**中的原型引用。一旦对象来自另一个 realm例如浏览器中的 iframe、跨窗口通信、Node.js 中跨 vm 上下文或 worker 传递的对象原型对象不同instanceof就会返回错误结果。规则的文档 docs/rules/no-instanceof-builtins.md 明确指出用instanceof判断对象类型存在限制因此推荐使用更安全的方式例如Object.prototype.toString.call(foo)或者使用 npm 包sindresorhus/is来判断对象类型。这条规则最初是为了取代已被废弃的no-instanceof-array与no-array-instanceof规则——在 docs/deleted-and-deprecated-rules.md 中记录了两个旧规则的移除原因均为由no-instanceof-builtins取代因为它覆盖了更多场景。规则行为与完整示例规则对以下instanceof用法一律报告错误并给出对应的推荐替代写法// ❌ foo instanceof String; // ✅ typeof foo string; // ❌ foo instanceof Number; // ✅ typeof foo number; // ❌ foo instanceof Boolean; // ✅ typeof foo boolean; // ❌ foo instanceof BigInt; // ✅ typeof foo bigint; // ❌ foo instanceof Symbol; // ✅ typeof foo symbol; // ❌ foo instanceof Array; // ✅ Array.isArray(foo); // ❌ foo instanceof Function; // ✅ typeof foo function; // ❌ foo instanceof Object; // ✅ Object.prototype.toString.call(foo) [object Object]; // 借助 sindresorhus/is import is from sindresorhus/is; // ❌ foo instanceof Map; // ✅ is(foo) Map;需要说明的是规则中的示例覆盖了两类对象基本类型包装器String、Number、Boolean、BigInt、Symbol和对象类型Array、Function、Object、Map。前者在 loose 策略下即被拦截后者中的Map属于 strict 策略的覆盖范围详见下文策略选项。除了裸标识符规则还支持globalThis.Array、window.Array、self.Array、global.Array这类通过全局对象属性访问的形式。从源码看rules/no-instanceof-builtins.js 维护了globalThis、global、self、window四个全局对象名当instanceof右侧是全局对象 标识符属性的成员表达式且确认是全局标识符时同样会命中例如// ❌ foo instanceof globalThis.String; // ❌ foo instanceof window.Array;自动修复与编辑器建议哪些可以一键改哪些只能手动阅读源码可以发现规则对不同构造函数的处理方式并不相同这一点直接影响你的使用体验自动修复--fix生效foo instanceof Array→Array.isArray(foo)源码中 replaceWithFunctionCall 将整个表达式替换为对Array.isArray的调用因此--fix可以直接改写foo instanceof Error仅在useErrorIsError: true时→Error.isError(foo)同样走函数调用替换路径foo instanceof Function→typeof foo function走 replaceWithTypeOfExpression 的typeof替换路径。注意当instanceof右侧即Function标识符内部含有注释时规则只报告不修复避免破坏注释。编辑器建议suggestion--fix不生效String、Number、Boolean、BigInt、Symbol这五个基本类型包装器规则只报告错误并附带一条名为Switch to \typeof … {{type}}的建议见 [rules/no-instanceof-builtins.js](https://link.gitcode.com/i/3deb762f723995ed04263ca200d8616b#L200-L212)。这类修复只能通过编辑器内的应用建议操作手动完成原因是从instanceof String改为typeof foo string 属于语义层面的改写交给用户确认更稳妥。仅报告无任何修复strict 策略下其余内置构造函数Map、Set、Date、RegExp、Promise、错误类型等以及通过include指定的构造函数规则只报告错误不提供自动改写。修复器还有两个值得注意的细节低优先级左操作数会加括号。当instanceof左侧是a b这类低优先级表达式时替换会产出typeof (a b) function而不是错误的typeof a b function。测试 test/no-instanceof-builtins.js 与快照 test/snapshots/no-instanceof-builtins.js.md 均验证了这一点Vue 模板中会选用安全引号。规则通过checkVueTemplate包装能够检查template与script中的表达式并且修复器会依据 Vue 表达式容器外层使用的引号类型自动选择单引号或双引号避免生成语法错误的字符串字面量见 rules/no-instanceof-builtins.js。测试中包含了v-ifarray instanceof Array等 Vue 场景的用例。配置选项详解规则共提供四个选项均通过对象形式传入schema 定义见 rules/no-instanceof-builtins.js默认值统一为{strategy: loose, include: [], exclude: [], useErrorIsError: false}。strategy类型loose | strict默认值loose匹配策略loose—— 匹配基本类型包装器String、Number、Boolean、BigInt、Symbol构造函数、Function和Arraystrict—— 匹配所有内置构造函数。unicorn/no-instanceof-builtins: [ error, { strategy: strict, }, ]从源码看两种策略的差异非常直观loose只依赖固定的primitiveWrappers五个包装器加上Array、Function的特殊处理strict则在include之外还叠加了一份覆盖错误类型、集合类型、类型化数组等内置构造函数的清单strictStrategyConstructors见 rules/no-instanceof-builtins.js。strict策略下被拦截的构造函数完整清单以当前仓库源码为准错误类型Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError、AggregateError、SuppressedError定义于 rules/shared/builtin-errors.js集合类型Map、Set、WeakMap、WeakRef、WeakSet数组与类型化数组ArrayBuffer以及Int8Array、Uint8Array、Uint8ClampedArray、Int16Array、Uint16Array、Int32Array、Uint32Array、Float16Array、Float32Array、Float64Array、BigInt64Array、BigUint64Array定义于 rules/shared/typed-array.js其他数据类型Object、RegExp、Promise、Proxy、DataView、Date、SharedArrayBuffer、FinalizationRegistry。测试 test/no-instanceof-builtins.js 对上述每一个构造函数都提供了对应的非法用例strict策略下这些用例全部会命中报告。include类型string[]默认值[]指定需要额外校验的构造函数。该选项在loose与strict策略下都生效——loose策略下forbiddenConstructors仅由include构成也就是说只使用include而保持默认的loose策略时规则只校验你显式列出的构造函数。unicorn/no-instanceof-builtins: [ error, { include: [ WebWorker, HTMLElement, ], }, ]例如测试中的用例foo instanceof WebWorker在默认配置下是合法的但加上include: [WebWorker]后即被报告见 test/no-instanceof-builtins.js。该选项特别适合自定义类型以及环境相关的全局构造函数。exclude类型string[]默认值[]指定需要排除的构造函数且优先级高于其他所有规则逻辑。在源码中即使构造函数命中了禁止清单只要其名字出现在exclude中就会直接放行见 rules/no-instanceof-builtins.js。unicorn/no-instanceof-builtins: [ error, { exclude: [ String, Number, ], }, ]测试验证了exclude: [Function]、exclude: [Array]、exclude: [String]时对应代码均被判定为合法见 test/no-instanceof-builtins.js。当你因某些历史代码或框架要求不得不保留个别instanceof判断时用exclude放行比整体关闭规则更精确。useErrorIsError类型boolean默认值false指定是否使用Error.isError()来判断错误对象。当开启后foo instanceof Error会被自动修复为Error.isError(foo)unicorn/no-instanceof-builtins: [ error, { strategy: strict, useErrorIsError: true, }, ]Error.isError()是 TC39 提出的is-error提案中的方法相比instanceof Error更稳健跨 realm 也可靠。该选项与strategy相互独立即便使用默认的loose策略只要开启useErrorIsErrorfoo instanceof Error同样会被报告并给出自动修复测试见 test/no-instanceof-builtins.js。需要特别留意文档中的警告该选项未来某个时间点会被移除原文档标注 This option will be removed at some point in the future.。一旦Error.isError()成为语言标准并被普遍支持这个开关预计会被默认行为取代。若你正在长期维护的项目中考虑该选项建议关注提案进展并做好迁移准备。与之相关的是独立的 prefer-error-is-error 规则——它专门偏好Error.isError()并且还会捕获Object.prototype.toString.call(error) [object Error]这类旧式 brand 检查可作为本项目内配套使用的参考。源码实现原理规则是如何工作的规则的完整实现位于 rules/no-instanceof-builtins.js核心逻辑可以概括为四个步骤监听二元表达式通过context.on(BinaryExpression, ...)钩子扫描所有二元表达式仅关注operator instanceof的节点rules/no-instanceof-builtins.js解析右侧构造函数getConstructor识别右侧节点——裸标识符String、Map等或全局对象 属性成员表达式globalThis.String等。对于成员表达式还要求对象确实为全局标识符避免误伤局部变量例如const window {Array}; foo instanceof window.Array是合法的测试中有对应用例按构造函数分流Array与开启选项时的Error走函数调用替换Function走typeof替换五个基本类型包装器提供typeof建议其余构造函数则依据forbiddenConstructors集合判断是否报告产出报告与修复返回带fix自动修复或suggest建议的报告对象。规则元数据中声明了fixable: code与hasSuggestions: true因此同时支持命令行--fix与编辑器内联建议见 rules/no-instanceof-builtins.js。如何在本项目与你的项目中验证与使用仓库内为该规则配备了完善的快照测试主测试文件 test/no-instanceof-builtins.js 覆盖了 loose/strict 两种策略、include/exclude、useErrorIsError、全局对象属性访问、低优先级左操作数、Vue 模板表达式需配合 Vue 解析器等场景所有期望输出记录在 test/snapshots/no-instanceof-builtins.js.md 中例如foo instanceof String会报告 Avoid usinginstanceoffor type checking as it can lead to unreliable results. 并给出typeof foo string的建议。在你自己的项目中启用该规则的方式与项目中其他 unicorn 规则一致安装eslint-plugin-unicorn后直接在 ESLint 配置中引用插件并配置规则扁平配置同样适用// eslint.config.js扁平配置示意 import unicorn from eslint-plugin-unicorn; export default [ unicorn.configs.recommended, { rules: { unicorn/no-instanceof-builtins: [error, {strategy: strict}], }, }, ];运行npx eslint --fix .即可让Array、Function以及开启useErrorIsError时的Error场景自动完成改写其余场景会以错误 建议的形式提示你手动确认。小结no-instanceof-builtins用一条规则覆盖了 JavaScript 中最容易踩坑的一类类型判断写法跨 realm 下instanceof结果不可靠、基本类型包装器的行为与直觉相悖。它提供了loose/strict两档策略、include/exclude的精确放行/收紧手段以及对Error.isError()的前瞻支持配合自动修复与编辑器建议能够在几乎零负担的情况下把项目里的脆弱类型检查逐步迁移到typeof、Array.isArray、Object.prototype.toString等稳健方案上。如果你在维护遗留代码库也可以从废弃规则 docs/deleted-and-deprecated-rules.md 中的迁移记录了解到no-instanceof-array与no-array-instanceof的用户应直接迁移到本规则其覆盖范围更广。【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考