拓冰建站拓冰建站
首页 / 资讯中心 / 正文

eslint-plugin-unicorn 规则解析:prefer-array-slice —— 用 `Arrayslice()` 替代只读场景下的 `Arraysplice()`

eslint-plugin-unicorn 规则解析prefer-array-slice —— 用Array#slice()替代只读场景下的Array#splice()【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn本篇技术指南围绕 eslint-plugin-unicorn 中的prefer-array-slice规则展开讲解它在何时检测、为何推荐的Array#slice()与Array#splice()的差异并结合 规则源码 与 测试用例 剖析其判定逻辑与边界行为。读完本文你将掌握该规则的触发条件、类型感知过滤机制、可用的编辑器自动修复suggestion以及如何在自己的项目中正确使用这一规则。规则概览只读意图的代码表达prefer-array-slice的核心诉求是当调用Array#splice()只是为了读取其返回的数组元素时应当改用Array#slice()。其规则描述为PreferArray#slice()overArray#splice()when reading from the returned array.从规则 meta 信息见 rules/prefer-array-slice.js可以看出规则类型suggestion仅产生建议性告警不判定为错误级别的严重问题推荐配置默认在 ✅recommended配置中启用在 ☑️unopinionated无观点配置中禁用——因为该规则属于有明确编码观点的建议不适合追求零主观约束的团队可自动修复支持 ESLint 的 editor suggestions 机制即编辑器可提示一键将splice改写为slice手动触发的修复而非自动应用适用语言js/js同时覆盖 JavaScript 与 TypeScript 场景后者依赖类型信息。该规则已通过 rules/index.js 注册进规则索引作为项目 300 条规则中的一员随插件一同发布。为什么推荐可变与不可变语义的取舍Array#splice()会就地修改源数组mutate删除元素的同时返回被删除的元素组成的新数组。而Array#slice()是纯读取操作不改变源数组返回的是原数组的一段浅拷贝。当代码形如array.splice(2)[0]时开发者真正的意图往往只是“取出第 2 个元素之后的第一个元素”并不想破坏源数组。此时splice的副作用属于无意的隐式变更可能引发难以排查的 bug——例如后续代码再次读取array时发现元素已被删除。prefer-array-slice正是在这类“读取返回值”场景下将可变操作改写为不可变操作让只读意图在代码层面被显式表达既消除副作用风险也提升可读性。触发条件何时报告该规则只对满足以下全部条件的splice调用报告问题见 rules/prefer-array-slice.js必须是标准方法调用splice作为方法名、非可选调用splice?.()不算、非可选成员?.splice()不算、非计算属性array[splice]()不算、且恰好只有1 个参数splice(index, deleteCount)不算返回结果必须被“只读访问”满足以下任一形态下标索引访问splice(index)[0]、splice(index)[offset]即紧接着被[n]读取.at()调用splice(index).at(0)即紧接着被.at(n)读取接收者receiver不能是已知的非数组通过类型信息判断若接收者明确不是数组则跳过见下文。为什么限定为 1 个参数因为array.splice(index, deleteCount)的第二个参数deleteCount明确表达了“我要删除若干个元素”的变更意图此时splice是合理的规则不介入。同理array.splice(index)单独调用不读取返回值也在规则放行之列——文档中的正例也印证了这两点。例外赋值与删除操作不报告“只读访问”的判定对赋值类操作保持克制。从 rules/utils/is-left-hand-side.js 的实现看以下场景会被判定为“左值”而非“读取”从而不报告array.splice(index)[0] value写入元素delete array.splice(index)[0]删除元素解构、更新表达式等出现在赋值目标位置的访问这些场景虽然也立即消费了返回值但语义上是写操作替换为slice会产生行为差异因此规则谨慎地将其排除对应 测试用例 中的 valid 用例。官方示例速览文档给出了四组典型示例见 docs/rules/prefer-array-slice.md// ❌ 报告读取返回值但会污染 process.argv const foo process.argv.splice(2)[0]; // ✅ 推荐 const foo process.argv.slice(2)[0];// ❌ 报告.at(0) 同样属于只读读取 const foo array.splice(index).at(0); // ✅ 推荐 const foo array.slice(index).at(0);// ✅ 放行不读取返回值splice 的变更语义是操作本身的一部分 array.splice(index);// ✅ 放行带 deleteCount明确表达删除意图 array.splice(index, deleteCount)[0];最后一行体现了规则的边界哲学当有意的变更mutation本身就是操作目的时请继续使用Array#splice()。源码级解析三处关键判定1. 下标访问判定isIndexedAccessrules/prefer-array-slice.js 中的isIndexedAccess要求父节点是计算属性成员表达式computed: true如[0]而非.at、非可选链optional: false且splice调用本身是该访问的对象node.parent.object node同时该访问不能是左值。2..at()调用判定isAtCallrules/prefer-array-slice.js 中的isAtCall要求.at是普通成员访问且外层是参数个数恰为1的at()方法调用。因此array.splice(index).at()无参数和array.splice(index).at(0, extra)多余参数都不会触发报告对应测试中的 valid 用例见 test/prefer-array-slice.js。3. 非数组接收者过滤shouldReportReceiverrules/prefer-array-slice.js 使用isKnownNonArray判断接收者是否为“已知非数组”并显式指定了接收者类型检查选项const receiverTypeOptions { checkClassHeritage: true, // 检查类继承链 checkClassSyntax: true, // 检查类语法声明 treatMixedUnionAsNonTarget: true, // 混合联合类型视为非目标 };这意味着规则在报告前会谨慎排除以下“非数组”情况避免误报自定义类实例const object {splice() { return []; }}; object.splice(index)[0]声明为Set、string等非数组类型的变量具有自定义splice方法的类型。而一个值得注意的实现细节是规则并未使用共享的shouldSkipKnownNonArrayReceiver工具而是自带接收者选项。其源码注释说明把 typed array如Uint8Array视为非数组在这里并无影响——因为typed array 本身没有splice()方法根本不会被报告。该接收者判定能力由 rules/utils/is-array.js 导出的isKnownNonArray提供它基于createTypeCheckers实现覆盖表达式形态ObjectExpression、FunctionExpression、NewExpression等与类型标注形态如TSArrayType两类判断。类型感知TypeScript 场景下的精确过滤得益于项目统一使用的类型检查基础设施该规则在 TypeScript 项目开启typescript-eslint解析器与类型信息中表现出更精确的行为测试文件 test/prefer-array-slice.js 完整覆盖了这些场景报告invalid的 TS 用例显式类型标注declare const array: string[]; array.splice(index)[0]类型别名type Strings string[]; declare const array: Strings; ...类型断言(array as string[]).splice(index)[0]索引类型参数array.splice(index as number)[0]、array.splice(index!)、array.splice(index satisfies number)未知类型declare const value: unknown; value.splice(index)[0]继承自Array的子类class ArraySubclass extends Array {} new ArraySubclass().splice(0)[0]、class ArraySubclass extends Arraynumber {...}this类型function method(this: string[]) { return this.splice(0)[0]; }动态构造declare const ArrayConstructor: typeof Array; new ArrayConstructor().splice(0)[0]放行valid的 TS 用例明确非数组declare const set: Setstring; set.splice(index)[0]、declare const string: string; ...自定义接口interface Custom { splice(index: number): string[]; } declare const value: Custom; ...混合联合类型treatMixedUnionAsNonTarget生效declare const value: string[] | Custom; value.splice(index)[0]类型信息下静态方法中的thisclass ArraySubclass extends Array { static method() { return this.splice(0)[0]; } }——静态上下文中this是构造函数而非数组实例其中class ArraySubclass extends Array { method() { return this.splice(0)[0]; } }在非类型感知下是 invalid会报告而在类型感知下取决于能否确认继承链指向Array——测试第 93 行的用例显示当value的运行时类型被推断为自定义Custom时则放行体现了类型信息对误报的抑制作用。自动修复与编辑器建议该规则声明了hasSuggestions: true见 rules/prefer-array-slice.js并提供一条建议修复suggestion错误消息Prefer Array#slice() over Array#splice() when reading from the returned array.建议消息Use Array#slice().修复动作fixer.replaceText(node.callee.property, slice)——仅将方法名splice替换为slice不改动参数与接收者。由于splice与slice在此场景下的参数签名完全兼容单参数start这个替换是行为安全的array.splice(index)返回[index, 之后所有元素]的新数组与array.slice(index)在只读场景下返回相同的内容而后者不产生副作用。在支持 ESLint suggestions 的编辑器VS Code 等中你可以手动触发快速修复一键应用。使用与验证在项目中启用该规则的方式与其他规则一致——使用recommended配置即默认开启// eslint.config.jsflat config import unicorn from eslint-plugin-unicorn; export default [ unicorn.configs[flat/recommended], // 或仅启用单条规则 // {plugins: {unicorn}, rules: {unicorn/prefer-array-slice: error}}, ];若团队希望自行约束可通过规则名单独配置开关与级别{ rules: { unicorn/prefer-array-slice: [error] } }运行npx eslint --fix-dry-run可以预览建议修复--fix-type suggestion则可自动应用所有 suggestion 类修复。规则的完整行为矩阵均可通过 test/prefer-array-slice.js 中的快照测试验证其 valid 数组列出 25 个放行用例invalid 数组列出 12 个报告用例并额外覆盖 TypeScript 解析器scripts/parsers.js 提供typescriptEslintParser与类型感知projectService两类测试模式是理解该规则边界的首选参考资料。总结prefer-array-slice通过“方法名 参数个数 后续访问形态 接收者类型”四重判定精准识别出“用可变操作表达只读意图”的代码模式报告条件单参数splice()的返回值紧接着被[n]下标或.at(n)只读消费放行条件带deleteCount、不读取返回值、赋值/删除类左值访问、接收者确认为非数组类型修复方式手动触发的 editor suggestion将方法名安全替换为slice。将该规则与recommended配置一起使用可以在不改变行为的前提下让代码的只读意图更明确并消除splice副作用带来的潜在隐患。【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门