
ESLint 规则 no-array-constructor 深度解析为什么数组应使用字面量写法【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint本篇文章围绕 ESLint 内置规则no-array-constructor展开讲解它为何禁止使用Array构造函数创建数组、在何种场景下允许例外以及它如何支持 JavaScript 与 TypeScript 语法。读完本文你将完整掌握该规则的判定逻辑、可自动修复的行为边界以及何时应关闭此规则。规则背景为什么Array构造函数被普遍反对在 JavaScript 中Array构造函数可以通过多种方式创建数组但社区普遍更倾向于使用数组字面量[]写法原因主要有两个单参数陷阱Array构造函数只接收一个数字参数时不会创建一个包含该数字的数组而是创建一个长度为该数字的空数组稀疏数组。例如Array(3)创建的是长度为 3 的稀疏数组而不是[3]。这种语义极易引发困惑和隐藏 bug。Array全局对象可能被重新定义在全局作用域中Array标识符可以被赋值或遮蔽直接使用new Array()可能调用到的是被改写过的实现。唯一的例外场景是刻意使用单个数字参数来创建指定长度的稀疏数组这是Array构造函数独有的、字面量无法直接等价替代的能力。因此规则允许Array(500)、new Array(someArray.length)这类用法而字面量[500]与Array(500)的语义完全不同绝不可互相替换。规则详情该规则禁止使用Array构造函数包括new Array()调用形式与直接调用形式Array()但放行上面提到的单数字参数稀疏数组场景。不正确的代码示例/*eslint no-array-constructor: error*/ Array(); Array(0, 1, 2); new Array(0, 1, 2); Array(...args);以上代码都会触发no-array-constructor报错其中Array(...args)这种展开参数的形式同样在禁止之列详见下文源码解析中对SpreadElement的处理。正确的代码示例/*eslint no-array-constructor: error*/ Array(500); new Array(someOtherArray.length); [0, 1, 2]; const createArray Array new Array();前两行利用了规则的“单个数字参数”例外[0, 1, 2]是推荐的字面量写法最后一行中Array被局部函数参数遮蔽不再指向全局Array构造函数因此不触发规则这一点与源码中的全局变量判定逻辑一致见下文。TypeScript 语法支持该规则额外支持 TypeScript 类型语法。由于 TypeScript 中ArrayFoo常用于类型标注而非构造调用规则对此进行了区分。正确的 TypeScript 代码示例/*eslint no-array-constructor: error*/ new Arraynumber(1, 2, 3); new ArrayFoo(); Arraynumber(1, 2, 3); ArrayFoo(); Array?.foo();带类型参数的ArrayFoo会被视为类型引用而非数组构造因此放行Array?.foo()是访问Array上的属性方法也不属于构造调用。不正确的 TypeScript 代码示例/*eslint no-array-constructor: error*/ new Array(); new Array(0, 1, 2); Array?.(x, y); Array?.(0, 1, 2);无类型参数的构造调用即使带有可选链?.依然会被报告。关于可选链的处理细节请参考 源码实现 与 TypeScript 测试用例。源码实现规则到底如何判定该规则对应的核心实现位于 lib/rules/no-array-constructor.js规则的元信息声明如下规则类型meta.type为suggestion与文档 front matter 中的rule_type: suggestion一致声明了fixable: code与hasSuggestions: true说明它既支持直接自动修复也支持提供修复建议schema: []表示该规则不接受任何配置选项监听CallExpressionArray()形式与NewExpressionnew Array()形式两类 AST 节点见 lib/rules/no-array-constructor.js。判定核心逻辑check函数从 check 函数 可以看到命中报错需要同时满足三个条件调用对象必须是名为Array的裸标识符node.callee.type ! Identifier || node.callee.name ! Array时直接返回因此foo.Array()、globalThis.Array、new Array.foo等成员访问形式不会被报告不得携带类型参数node.typeArguments存在时直接返回这正是 TypeScript 中ArrayFoo放行的原因不得是单个非展开参数node.arguments.length 1 node.arguments[0].type ! SpreadElement时直接返回这就是“单数字参数创建稀疏数组”例外在源码中的落点而Array(...args)是SpreadElement不满足此条件所以会被报告。此外规则还会调用 getVariableByName 沿作用域链向上查找名为Array的变量并且只有在该变量是预定义全局变量variable.identifiers.length 0即没有任何声明时才报错。这就是上文中const createArray Array new Array()不报错的原因——局部参数遮蔽了全局Array。测试用例中的var Array; new Array;与关闭全局Arrayglobals: { Array: off }的场景也验证了这一点见 tests/lib/rules/no-array-constructor.js。自动修复与修复建议的分工规则提供了两种修复途径对应三条消息见 源码 messages 定义preferLiteral报告主体消息“The array literal notation [] is preferable.”useLiteral/useLiteralAfterSemicolon修复建议消息“Replace with an array literal.”必要时补充前置分号。从源码看fix直接自动修复与suggest修复建议是互斥的分工当不应建议即shouldSuggest为假时直接修复生效将Array(...)替换为[...]字面量当应建议时shouldSuggest为真直接修复返回null只提供修复建议供开发者手动应用。shouldSuggest为真的三种情形见 lib/rules/no-array-constructor.js节点带有可选链node.optional例如Array?.(0, 1, 2)——修复会改变可选语义不宜强制参数数量大于 0 但非展开参数少于 2 个例如Array(...args)、Array(5, ...args)——修复为[...args]会改变调用语义只给建议Array构造函数表达式内存在注释——hasCommentsInArrayConstructor检测到注释时为避免破坏注释而只给建议测试中大量/*a*/Array()/*b*/场景验证了这一点。分号自动插入ASI的补偿处理这是本规则最精巧的实现细节。JavaScript 的自动分号插入ASI规则下Array()或new Array()出现在某些语句之后时无需前置分号但一旦被替换为[...]字面量[可能被解析为上一表达式的属性访问或其它延续导致语义改变。因此规则借助 needsPrecedingSemicolon 与 isStartOfExpressionStatement 判断若替换为[...]后需要补充分号则生成;[...]并报告useLiteralAfterSemicolon否则生成[...]并报告useLiteral。例如测试中foo\nArray()会被修复为foo\n;[]而语句起始位置的Array()则直接修复为[]。相关的分号判断测试用例集中在 tests/lib/rules/no-array-constructor.js覆盖了a、a、return、yield、export、import、JSX 等大量前后语句形态。配置选项此规则没有选项。该规则不接收任何配置参数schema: []只需指定严重级别即可启用例如/*eslint no-array-constructor: error*/或在扁平配置中使用export default [ { rules: { no-array-constructor: error, }, }, ];需要注意的是该规则并未包含在eslint:recommended预设中规则元信息中recommended: false同时可在 tests/conf/eslint-recommended.js 与 conf/rule-type-list.json 中确认其未列入推荐集合需要手动开启。规则通过 lib/rules/index.js 中的懒加载映射注册到 ESLint 规则系统。何时不使用此规则该规则强制的是一个近乎普适的风格约定绝大多数代码库都应遵循。但如果你或你的团队偏好构造函数写法例如更习惯new Array()的显式性完全可以关闭此规则。此外在需要刻意创建指定长度的稀疏数组的场景中Array(n)是字面量无法替代的惯用法规则本身已将其作为例外放行无需担心误报。相关规则no-array-constructor在文档 front matter 中声明了关联规则no-new-wrappers禁止对String、Number、Boolean等原始包装对象使用newno-object-constructor禁止使用Object构造函数new Object()/Object()。三者共同构成 ESLint 中“使用字面量而非构造函数”的一组相关约定。如果你想了解规则在真实代码上的全部行为边界含注释、可选链、TypeScript 类型语法、ASI 分号补偿等可以直接运行仓库中的测试node --test tests/lib/rules/no-array-constructor.js。【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考