ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

eslint-plugin-unicorn `no-instanceof-builtins` 规则深度解析:快照测试、自动修复与安全类型检查实战指南

eslint-plugin-unicorn `no-instanceof-builtins` 规则深度解析:快照测试、自动修复与安全类型检查实战指南 eslint-plugin-unicornno-instanceof-builtins规则深度解析快照测试、自动修复与安全类型检查实战指南【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn本篇技术指南以 eslint-plugin-unicorn 中no-instanceof-builtins规则为核心结合其源码实现rules/no-instanceof-builtins.js、官方文档docs/rules/no-instanceof-builtins.md、单元测试test/no-instanceof-builtins.js与 AVA 快照test/snapshots/no-instanceof-builtins.js.md完整讲解该规则的报错信息、自动修复行为、strategy/include/exclude/useErrorIsError四个配置项以及它如何安全处理 Vue 模板、globalThis成员访问与低优先级左操作数等边界场景。读完本文你将掌握该规则从配置、报错到自动修复的完整工作链路并能在自己的 ESLint 项目中正确启用和调优它。规则概述为什么要禁止对内置对象使用instanceofno-instanceof-builtins是一条问题型type: problem规则其目的是禁止对内置对象使用instanceof进行类型检查。规则在源码中声明的描述为 Disallowinstanceofwith built-in objects对应报错信息为Avoid usinginstanceoffor type checking as it can lead to unreliable results.其根本原因在于instanceof依赖原型链判断存在跨 realm多个全局环境如 iframe、Worker 等失效的问题——来自不同 realm 的同一个内置构造器并不共享原型链导致foo instanceof Array可能对真正的数组返回false。因此规则文档建议改用更安全的方式例如Object.prototype.toString.call(foo)或者借助sindresorhus/is这类库进行类型判断见 docs/rules/no-instanceof-builtins.md。规则元信息速览从 rules/no-instanceof-builtins.js 的meta配置可以确认以下关键信息项目值说明typeproblem属于潜在缺陷类规则fixablecode支持--fix自动修复hasSuggestionstrue同时提供编辑器可手动应用的建议修复recommendedunopinionated属于非强制推荐配置languages[js/js]适用于 JS 文件且经 Vue 模板检查包装后同样作用于.vue模板表达式在规则配置层面recommended与unopinionated两个预置 config 都会启用该规则其默认选项为useErrorIsError: false、strategy: loose、include: []、exclude: []见 rules/no-instanceof-builtins.js。规则默认行为loose 策略下的报错与自动修复规则的默认匹配策略是loose此时只针对原始类型包装构造器 FunctionArray共七类目标报错。从 test/no-instanceof-builtins.js 的looseStrategyInvalid用例可见其完整清单String、Number、Boolean、BigInt、Symbol对应源码 rules/no-instanceof-builtins.js 中的primitiveWrappers集合Function、Array在 test/snapshots/no-instanceof-builtins.js.md 中这些用例的快照结果清晰展示了自动修复的差异原始类型包装构造器 →typeof建议对于foo instanceof String规则报告错误并给出建议修复Suggestion不会在--fix时直接应用// 输入报错 foo instanceof String; // 建议修复 typeof foo string;Number、Boolean、BigInt、Symbol依次对应typeof foo number | boolean | bigint | symbol其中类型名由构造器名小写化得到见源码replaceWithTypeOfExpression中的constructorName.toLowerCase()rules/no-instanceof-builtins.js。建议的文案固定为 Switch totypeof … {{type}}.rules/no-instanceof-builtins.js。Array→Array.isArray()自动修复foo instanceof Array会被直接自动修复为Array.isArray(foo)Output 而非 Suggestion见快照 test/snapshots/no-instanceof-builtins.js.md因为该替换是无损且安全的。类似的直接修复还覆盖了大量形态[] instanceof Array→Array.isArray([])、[1,2,3] instanceof Array true→Array.isArray([1,2,3]) true、fun.call(1, 2, 3) instanceof Array、obj.arr instanceof Array、foo.bar[2] instanceof Array、(0, array) instanceof Array、function foo(){return[]instanceof Array}→function foo(){return Array.isArray([])}见 test/snapshots/no-instanceof-builtins.js.md可见修复逻辑对成员表达式、调用表达式、逗号表达式等左操作数都能稳定包裹。Function→typeof自动修复foo instanceof Function会自动修复为typeof foo function快照 test/snapshots/no-instanceof-builtins.js.md。低优先级左操作数的括号处理a b instanceof Function快照中存在一组专门的用例对应测试 test/no-instanceof-builtins.js用于验证低优先级左操作数必须加括号使typeof作用于整个表达式a b instanceof Function→typeof (a b) functiona b instanceof String→typeof (a b) stringa - b instanceof Function→typeof (a - b) function(a b) instanceof Function→typeof (a b) function原已加括号则保持对应快照见 test/snapshots/no-instanceof-builtins.js.md。这一行为由源码中的括号判断实现只有当左操作数未加括号、且满足shouldAddParenthesesToUnaryExpressionArgument(left, typeof)时才补上typeof (...)否则直接前缀typeofrules/no-instanceof-builtins.js。该工具函数基于运算符优先级判断getPrecedence(node) PRECEDENCE_UNARY时需加括号避免生成typeof a b function这类语义错误的代码见 rules/utils/should-add-parentheses-to-unary-expression.js。strict 策略覆盖全部内置构造器当配置strategy: strict时规则会额外匹配一组内置构造器清单源码 rules/no-instanceof-builtins.js 的strictStrategyConstructors分类构造器错误类型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该清单与测试文件中的strictStrategyInvalid用例一一对应test/no-instanceof-builtins.js。在 strict 策略下这些构造器如fooStrict instanceof Map、fooStrict instanceof Int8Array、fooStrict instanceof Date等会报出同样的错误信息但不提供自动修复——快照中均只有 Message、没有 Output 或 Suggestion例如 test/snapshots/no-instanceof-builtins.js.md 的Map用例。原因很直观对这些复杂内置对象并没有单一可靠的替代写法规则只负责提醒开发者改用安全方案。需要注意strict 策略是在 loose 七类目标之上叠加匹配的。测试中 strict 策略的用例集合为[...looseStrategyInvalid, ...strictStrategyInvalid]test/no-instanceof-builtins.js因此fooStrict instanceof String在 strict 下同样报错并给出typeof建议。配置示例unicorn/no-instanceof-builtins: [ error, { strategy: strict, }, ]include / exclude自定义匹配名单除内置清单外规则支持通过include与exclude两个数组选项定制匹配范围其配置 schema 与默认值见 rules/no-instanceof-builtins.js。include追加需要校验的构造器默认[]用于把内置清单之外的构造器加入检查。文档示例docs/rules/no-instanceof-builtins.mdunicorn/no-instanceof-builtins: [ error, { include: [ WebWorker, HTMLElement, ], }, ]测试与快照验证了该行为fooInclude instanceof WebWorker与fooInclude instanceof HTMLElement在配置include: [WebWorker]、include: [HTMLElement]后均会报错test/no-instanceof-builtins.js、test/snapshots/no-instanceof-builtins.js.md。与之对照默认 loose 策略下foo instanceof WebWorker是合法用例test/no-instanceof-builtins.js。从实现上看include在两种策略下的作用不同rules/no-instanceof-builtins.jsconst forbiddenConstructors new Set(strategy strict ? [...strictStrategyConstructors, ...include] : include);strict 策略include追加到内置清单之后loose 策略include直接构成唯一的匹配来源此时规则匹配范围 七类默认目标 include 列表。exclude优先排除指定构造器默认[]用于从所有匹配中排除指定构造器且优先级高于其他所有配置包括默认目标和include。文档示例unicorn/no-instanceof-builtins: [ error, { exclude: [ String, Number, ], }, ]测试验证了排除优先级fooExclude instanceof Function/Array/String在配置exclude: [Function]、[Array]、[String]后全部变为合法test/no-instanceof-builtins.js。实现上规则在拿到构造器后第一步就检查exclude.includes(constructor.name)命中则直接返回rules/no-instanceof-builtins.js。useErrorIsError用Error.isError()判定错误对象useErrorIsError默认false用于决定当右侧是Error时是否将其修复为提案中的Error.isError()调用。开启后fooErr instanceof Error会被自动修复为Error.isError(fooErr)快照 test/snapshots/no-instanceof-builtins.js.mdunicorn/no-instanceof-builtins: [ error, { strategy: strict, useErrorIsError: true, }, ]开启且匹配Error走函数调用修复分支替换为Error.isError(...)源码 rules/no-instanceof-builtins.js开启但匹配其他错误类型如err instanceof EvalError、RangeError等仍然报错但不产生修复见 test/snapshots/no-instanceof-builtins.js.md关闭foo instanceof Error在 loose 策略下不会报错不属于七类默认目标在 strict 策略下报错但不提供修复。需要特别说明的是该选项文档已注明会在未来的某个版本移除docs/rules/no-instanceof-builtins.md因为Error.isError()仍是提案阶段 APITC39 proposal-is-error使用时需要关注其落地进度与运行环境兼容性。全局对象成员访问的识别与修复规则不仅匹配裸标识符还能识别通过globalThis/window/self/global访问的内置构造器其判定条件是非计算属性、属性为标识符、对象名属于四个全局对象名之一、且该对象确实指向全局对象isGlobalIdentifier校验见 rules/no-instanceof-builtins.js。快照中对应的典型修复test/snapshots/no-instanceof-builtins.js.mdfoo instanceof globalThis.String→ 建议typeof foo stringfoo instanceof globalThis.Function→ 自动修复typeof foo functionfoo instanceof globalThis.Array→ 自动修复globalThis.Array.isArray(foo)foo instanceof window.Array→window.Array.isArray(foo)foo instanceof self.Array→self.Array.isArray(foo)foo instanceof global.Array→global.Array.isArray(foo)注意修复时会保留引用前缀referenceText例如全局对象写法下Array分支生成${referenceText}.isArray(...)因此输出是globalThis.Array.isArray(foo)而非裸Array.isArray(foo)rules/no-instanceof-builtins.js。这能避免在const Array {isArray: () false};这类局部遮蔽场景下产生行为变化——测试专门覆盖了该用例修复后仍指向globalThis.Array快照 test/snapshots/no-instanceof-builtins.js.md。同时规则对伪全局访问保持克制当局部变量遮蔽了全局对象名如const globalThis {Array}; foo instanceof globalThis.Array、const window {Array}; foo instanceof window.Array或使用计算属性foo instanceof globalThis[Array]时均判定为合法test/no-instanceof-builtins.js。Vue 模板与script中的检查与修复规则通过checkVueTemplate(create)包装rules/no-instanceof-builtins.js使得监听器同时作用于.vue文件的模板表达式与script块。该包装器在检测到vue-eslint-parser提供的defineTemplateBodyVisitor时将同一组监听器同时注册到模板 body 与 script 上见 rules/utils/rule.js。快照中基于 vue 解析器的用例验证了模板与 script 内的行为test/snapshots/no-instanceof-builtins.js.md!-- 模板表达式自动修复 -- templatediv v-ifarray instanceof Array v-forelement of array/div/template !-- 修复为 -- templatediv v-ifArray.isArray(array) v-forelement of array/div/template !-- 带括号嵌套的模板表达式 -- templatediv v-if(( (( array )) instanceof (( Array )) ))/div/template !-- 修复为 -- templatediv v-if(( Array.isArray((( array ))) ))/div/template !-- 插值表达式 -- templatediv{{(( (( array )) instanceof (( Array )) )) ? array.join( | ) : array}}/div/template !-- 修复为 -- templatediv{{(( Array.isArray((( array ))) )) ? array.join( | ) : array}}/div/template !-- script 块 -- scriptconst foo array instanceof Array/script !-- 修复为 -- scriptconst foo Array.isArray(array)/script scriptfoo instanceof Function/script !-- 修复为 -- scripttypeof foo function/script值得注意的是模板环境下的引号适配生成typeof比较时规则会检测是否处于 Vue 表达式容器中若模板表达式外层使用双引号则改用单引号生成字符串字面量如v-iftypeof foo string避免引号冲突源码 rules/no-instanceof-builtins.js。修复实现的底层细节从源码看规则的自动修复由两个 generator 函数实现均基于 token 级别的精确替换replaceWithFunctionCallrules/no-instanceof-builtins.js用于Array/Error.isError分支。先调用fixSpaceAroundKeyword规整instanceof两侧空白然后在左操作数外层插入函数名(与)最后删除instanceoftoken 与右侧构造器 token。replaceWithTypeOfExpressionrules/no-instanceof-builtins.js用于typeof分支。按需给低优先级左操作数加括号把instanceoftoken 替换为再把右侧构造器替换为对应的小写类型字符串。两者都使用getParenthesizedRange获取包含外层括号的完整范围例如(fooErr) instanceof (Error)修复后为Error.isError((fooErr))快照 test/snapshots/no-instanceof-builtins.js.md从而保证多级括号、注释等细节在修复过程中被完整保留。快照中还有一个覆盖了大量嵌套括号与注释的极端用例修复输出逐行保留了所有注释与缩进test/snapshots/no-instanceof-builtins.js.md直观体现了该修复链的健壮性。另一个细节当右侧构造器内部含注释时如foo instanceof Function /* keep */Function与包装类型的自动修复/建议会被抑制源码 rules/no-instanceof-builtins.js 中的hasCommentsInside判断避免删除用户注释。快速上手与验证在项目中启用规则安装并启用eslint-plugin-unicorn后在 ESLint 配置中加入unicorn/no-instanceof-builtins: [ error, { strategy: strict, useErrorIsError: false, include: [], exclude: [], }, ]随后运行npx eslint --fix .即可对Array、Function、Error开启useErrorIsError时等场景执行自动修复对String、Number等包装类型会输出建议修复可在编辑器中手动应用。通过仓库测试与快照深入理解规则源码rules/no-instanceof-builtins.js官方文档docs/rules/no-instanceof-builtins.md单元测试test/no-instanceof-builtins.js约 40 个断言组覆盖 loose / strict / include / exclude / useErrorIsError / 全局对象 / Vue 模板 / 括号与注释等场景完整快照test/snapshots/no-instanceof-builtins.js.md共 2020 行逐条记录了每个无效用例的输入、报错位置、消息与修复输出是最直观的行为文档配套共享数据rules/shared/builtin-errors.js、rules/shared/typed-array.js运行规则相关测试可使用npx ava test/no-instanceof-builtins.js快照文件即由 AVA 自动生成与维护test/snapshots/no-instanceof-builtins.js.md头部注明由 AVA 生成实际快照数据保存在no-instanceof-builtins.js.snap中。总结no-instanceof-builtins是 eslint-plugin-unicorn 中一条防患于未然的问题型规则它以instanceof跨 realm 不可靠为核心动机用 loose / strict 两档策略覆盖从原始类型包装构造器到全部内置构造器的检查范围并通过 include / exclude / useErrorIsError 三个选项提供灵活的定制空间。它的自动修复对Array、Function与Error.isError场景能做到语义无损的 token 级替换对低优先级操作数、全局对象成员访问、Vue 模板与复杂括号注释环境均有完善的边界处理。快照文件test/snapshots/no-instanceof-builtins.js.md逐条固化了这些行为既是回归测试的守护也是理解该规则全部细节的最佳阅读材料。【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表