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

ESLint no-labels 规则完全指南:彻底禁用 JavaScript 标签语句

ESLint no-labels 规则完全指南彻底禁用 JavaScript 标签语句【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint本文是 ESLint 内置规则no-labels的深度技术指南。该规则用于禁止 JavaScript 中的标签语句Labeled Statements以及与标签搭配使用的break/continue跳转帮助团队规避一种极易出错、难以阅读的非主流流程控制方式。读完本文你将掌握该规则的全部选项allowLoop/allowSwitch的语义与用法、其底层 AST 检测原理、配套的测试用例以及何时应该关闭这条规则。文章以当前仓库 ESLint 源码 为事实依据展开。标签语句是什么break与continue的多层循环控制在 JavaScript 中标签语句Labeled Statement必须与break或continue搭配使用用于在多重重叠的循环之间精确控制流程跳出位置。规则文档给出了一个典型例子见 docs/src/rules/no-labels.mdouter: while (true) { while (true) { break outer; } }这里break outer保证代码不会陷入死循环控制权被交还给outer标签之后的下一条语句。如果把它改成普通的break控制流只会回到外层while语句从而造成死循环。虽然标签在某些场景下确实方便但它使用频率极低且被不少开发者视为一种补救式的流程控制手段——更容易出错、更难理解。no-labels规则正是为了消除这种写法而设计的。Rule Details规则检测什么该规则的目标是消除 JavaScript 中的标签语句使用。根据规则文档只要遇到标签语句本身或带标签的break/continue规则就会发出警告默认配置下。错误代码示例以下代码全部会被报告为错误示例摘自规则文档可在 docs/src/rules/no-labels.md 中查看/*eslint no-labels: error*/ label: while(true) { // ... } label: while(true) { break label; } label: while(true) { continue label; } label: switch (a) { case 0: break label; } label: { break label; } label: if (a) { break label; }注意标签不仅可以贴在while、switch上还可以贴在普通的代码块{}甚至if语句上规则对所有这些情况一律报告。正确代码示例以下写法不会触发警告——对象属性名label不是标签语句而普通不带标签的break/continue也不在规则的管辖范围内/*eslint no-labels: error*/ const f { label: foo }; while (true) { break; } while (true) { continue; }Options允许循环或 switch 上的标签规则提供两个布尔选项用来放行贴在循环语句或switch 语句上的标签选项类型默认值说明allowLoopbooleanfalse设为true时规则忽略贴在循环语句上的标签allowSwitchbooleanfalse设为true时规则忽略贴在 switch 语句上的标签需要强调的是标签语句在 JavaScript 中理论上可以贴在任何语句上而不只是循环和 switch。但这种用法极其罕见、不为大多数开发者所知容易造成困惑因此规则默认全禁只有通过上述两个选项显式放行。allowLoop放行循环标签{ allowLoop: true }配置下以下代码是正确的/*eslint no-labels: [error, { allowLoop: true }]*/ label: while (true) { break label; }allowSwitch放行 switch 标签{ allowSwitch: true }配置下以下代码是正确的/*eslint no-labels: [error, { allowSwitch: true }]*/ label: switch (a) { case 0: break label; }需要注意的是这两个选项的放行范围仅限于贴在对应语句上的标签。即便allowLoop/allowSwitch为true贴在普通代码块、if、var等语句上的标签以及对应的带标签break/continue依然会被报告这一点在测试用例中有充分体现见下文。源码剖析规则如何实现检测规则的完整实现位于 lib/rules/no-labels.js作者是 Nicholas C. Zakas。整条规则基于对 ESTree 标准 AST 节点的遍历实现关键点如下。meta 元信息类型、选项 schema 与消息在meta中lib/rules/no-labels.js可以看到type: suggestion——属于建议类规则与代码风格、可维护性相关defaultOptions: [{ allowLoop: false, allowSwitch: false }]——声明两个选项的默认值都是falseschema使用对象结构校验allowLoop与allowSwitch必须是boolean且additionalProperties: false禁止传入任何未知选项messages定义了三条报告消息unexpectedLabelUnexpected labeled statement.unexpectedLabelInBreakUnexpected label in break statement.unexpectedLabelInContinueUnexpected label in continue statement.核心逻辑scopeInfo栈 三种节点监听规则的核心算法lib/rules/no-labels.js用了一个手写的scopeInfo链表栈来跟踪当前标签贴在什么语句上进入LabeledStatement节点时把{ label, kind, upper }压入栈顶。其中kind由getBodyKind()判定若astUtils.isLoop(node)为真则kind为loop——isLoop的实现位于 lib/rules/utils/ast-utils.js通过正则/^(?:DoWhile|For|ForIn|ForOf|While)Statement$/u匹配覆盖do...while、for、for...in、for...of、while五类循环若节点类型是SwitchStatement则kind为switch其余情况代码块、if等一律为other。退出LabeledStatement节点时调用isAllowed(scopeInfo.kind)判断该种类是否被选项放行只有kind loop且allowLoop为真、或kind switch且allowSwitch为真时才放行否则报告unexpectedLabel。随后弹出栈顶。遇到BreakStatement/ContinueStatement时若节点带有label则调用getKind(label.name)沿着scopeInfo栈向上查找该标签对应的kind标签可以引用外层作用域定义的标签若该种类未放行则分别报告unexpectedLabelInBreak/unexpectedLabelInContinue。这就是默认全禁、按需放行语义的底层来源放行判断发生在两个层面——标签定义处LabeledStatement:exit与标签使用处BreakStatement/ContinueStatement二者独立判断因此即便allowLoop为真break A也只有在A确实贴着循环语句时才会被放行。测试验证规则行为的完整证据规则的测试位于 tests/lib/rules/no-labels.js使用RuleTester框架共 286 行覆盖了valid与invalid两类场景。valid部分验证了不会误报的写法tests/lib/rules/no-labels.js对象属性var f { label: foo ()}——属性键不是标签无标签的while (true) { break; }/continue;allowLoop: true下的A: while (a) { break A; }、A: do { if (b) { break A; } } while (a);、多层循环 switch 中continue AallowSwitch: true下的A: switch (a) { case 0: break A; }。invalid部分验证了各种必须报告的写法tests/lib/rules/no-labels.js其中几个细节值得注意label: while (true) { break label; }会同时产生两条错误unexpectedLabel标签定义处unexpectedLabelInBreak标签使用处A: var foo 0;即使开启allowLoop或allowSwitch依然报unexpectedLabel——因为var既不是循环也不是 switch属于other种类永不放行A: while (a) { break A; }在allowSwitch: true下依然报错反向证明选项的放行范围严格限定在对应语句种类上。这些用例完整验证了文档中所有示例行为是文档描述 代码行为的可靠佐证。与相关规则的协作规则文档的 front matter 声明了三条相关规则它们与no-labels共同构成对标签语句的完整治理体系且都已在 lib/rules/index.js 中注册no-extra-label禁止多余的标签——当标签没有实际跳转价值例如只贴了一层循环且break/continue不加标签效果相同时报告。该规则fixable: code可自动修复lib/rules/no-extra-label.js与no-labels的一刀切角度不同它只针对不必要的标签no-label-var禁止标签名与变量/函数名重名避免命名冲突造成的混淆no-unused-labels禁止声明了却从未被break/continue引用的标签。实际项目中你可以根据治理力度组合使用要么用no-labels彻底禁止标签要么用no-extra-labelno-label-varno-unused-labels允许必要且规范的标签存在。When Not To Use It何时关闭该规则规则文档明确给出结论如果你需要在代码中大量使用标签语句例如重循环嵌套场景下依赖标签跳出那么可以放心关闭这条规则。关闭后 ESLint 将不再对标签语句及其带标签跳转做任何提示交由团队自身的代码规范约束。小结no-labels默认同时禁止标签语句定义、带标签的break与continue通过allowLoop: true/allowSwitch: true可精准放行贴在循环或 switch 上的标签放行判断在标签定义处与使用处独立进行实现上依赖LabeledStatement、BreakStatement、ContinueStatement三类 AST 节点与一个scopeInfo栈见 lib/rules/no-labels.js循环种类的判定复用了 lib/rules/utils/ast-utils.js 中的isLoop行为完整性由 tests/lib/rules/no-labels.js 的 286 行测试用例保证与no-extra-label、no-label-var、no-unused-labels组合可实现对标签语句禁止或规范使用两种治理路线。【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

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

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