ESLint operator-assignment 规则详解要求或禁止赋值运算符简写形式【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslintoperator-assignment是 ESLint 内置的一条suggestion类型规则用于统一项目中「变量赋值 简单数学运算」的书写风格要么要求尽可能使用x y这样的简写形式要么彻底禁止简写、强制写成x x y。本文基于 docs/src/rules/operator-assignment.md 规则文档结合 lib/rules/operator-assignment.js 源码实现与 tests/lib/rules/operator-assignment.js 测试用例完整讲解其支持的运算符范围、两种选项的判定逻辑、自动修复能力与边界行为帮助你在项目中做出正确、安全的选择。规则背景JavaScript 的赋值运算符简写JavaScript 提供了一组把「赋值」与「简单数学运算」合并的简写运算符。例如x x 4可以缩写为x 4。该规则支持的简写形式与对应的分离写法如下Shorthand | Separate -----------|------------ x y | x x y x - y | x x - y x * y | x x * y x / y | x x / y x % y | x x % y x ** y | x x ** y x y | x x y x y | x x y x y | x x y x y | x x y x ^ y | x x ^ y x | y | x x | y注意规则不检查逻辑赋值运算符、||和??因为它们的短路short-circuiting求值行为与其他赋值运算符不同无法等值转换。这一判断在源码中也有对应体现never模式下prohibit 函数 通过astUtils.isLogicalAssignmentOperator(node.operator)定义于 lib/rules/utils/ast-utils.js显式跳过逻辑赋值运算符测试用例也验证了x x y、x y、x ?? y等代码在两种选项下均不报错见 tests/lib/rules/operator-assignment.js。与该规则互补的是 logical-assignment-operators 规则——它专门负责、||、??这三种逻辑赋值运算符的简写检查。Rule Details规则的检查逻辑该规则的核心行为是在可能的情况下要求或禁止赋值运算符简写。它只作用于上表中列出的运算符具体判定分为两类见源码 isCommutativeOperatorWithShorthand 与 isNonCommutativeOperatorWithShorthand可交换运算符commutative*、、^、|。它们的操作数顺序不影响结果因此x y * x和x x * y都满足转换为x * y的条件前者仍然会被报告但自动修复有额外限制见下文。不可交换运算符non-commutative、-、/、%、、、、**。它们只要求「被赋值的引用出现在二元表达式的左侧」即x x y可转换为x y而x y x不能转换并不总是可交换的例如x abc时y x与x y结果不同。同一引用的判定isSameReference判断「左侧被赋值引用」与「右侧二元表达式中的操作数」是否为同一引用依赖 ast-utils 中的 isSameReference。该函数对Identifier、ThisExpression、Super、Literal、MemberExpression、ChainExpression、PrivateIdentifier等节点类型进行递归比较并且支持静态可计算的属性名等价匹配如x.y x[y]视为同一引用。测试中的这些用例即来源于此x[0] x[0] / y可修复为x[0] / y0是字面量toString()不会被调用安全x[fn()] x[fn()] y不报错两次函数调用fn()结果可能不同不属于同一引用x[y] x[y] z不报错y是变量而非静态键无法判定等价。Options 配置该规则只有一个字符串选项always默认——在可能的情况下要求使用赋值运算符简写形式never——禁止赋值运算符简写形式。配置方式示例eslint.config.jsexport default [ { rules: { operator-assignment: [error, always], // 或 // operator-assignment: [error, never], }, }, ];源码层面规则的defaultOptions与schema定义于 metaschema使用enum: [always, never]校验选项合法性defaultOptions: [always]保证未配置时回退到默认行为create函数顶部通过context.options[0] never分支决定注册verify检查应使用简写却没用还是prohibit检查用了简写。规则类型为suggestion且fixable: code意味着它同时提供自动修复能力。此外该规则默认不包含在eslint:recommended中recommended: false需要显式开启。always要求使用简写形式不正确的代码默认always选项/*eslint operator-assignment: [error, always]*/ x x y; x y * x; x[0] x[0] / y; x.y x.y z;正确的代码默认always选项/*eslint operator-assignment: [error, always]*/ x y; x y; x y * z; x (x * y) * z; x[0] / y; x[foo()] x[foo()] % 2; x y x; // is not always commutative (e.g. x abc)其中几个关键边界值得注意均有测试用例佐证x y * x会被报告但不会被自动修复。因为*是可交换运算符isSameReference(left, expr.right)同样命中但源码注释明确说明如果a和b都自定义了valueOf()把a b * a修成a * b会改变valueOf()的调用顺序因此这类修复被刻意跳过见 verify 函数 及测试中output: null的用例。x (x * y) * z右侧不是单一二元运算的左操作数匹配右侧二元表达式x * y的右操作数是z不满足转换条件因此不报错。x y x属于不可交换运算符且x出现在右侧expr.right不满足「左操作数相同」或「可交换运算符的右操作数相同」任一条件不报错。更复杂的成员访问如x.y[z[a]][0].b x.y[z[a]][0].b * 2会被报告但不修复——修复会触发更多次 getter源码 canBeFixed 规定只有Identifier或对象为Identifier/ThisExpression且非计算属性或属性为字面量的MemberExpression才可安全修复。never禁止使用简写形式不正确的代码never选项/*eslint operator-assignment: [error, never]*/ x * y; x ^ (y z) / foo();正确的代码never选项/*eslint operator-assignment: [error, never]*/ x x y; x.y x.y / a.b;never模式下自动修复会把简写展开为完整写法但需要处理两类棘手问题运算优先级例如foo * bar 1修复为foo foo * (bar 1)、foo bar baz修复为foo foo (bar baz)、foo bar 1修复为foo foo (bar 1)——修复器会比较右操作数的优先级必要时自动加括号见 prohibit 函数 与相应测试用例。token 相邻性修复可能产生两个无法相邻的 token例如foobar修复为foo foo bar中间补一个空格、foo//^bar$/修复为foo foo/ /^bar$/。源码通过astUtils.canTokensBeAdjacent判断是否需要插入空格prohibit 函数。注释保护如果修复会删除或复制注释则放弃修复return null例如x /*1*/ x y、x //1\n y等用例。另外never模式下foo.bar.baz qux这类嵌套成员访问同样只报告不修复——展开后会让foo.bar的 getter 从触发一次变为触发两次行为可能改变。自动修复与注释、getter 的安全性该规则在两种模式下都声明了fixable: code可在eslint --fix下工作。修复器对安全性非常保守核心依据来自 canBeFixed 与commentsExistBetween检查getter/setter 激活次数foo.bar.baz foo.bar.baz qux若修复为foo.bar.baz quxfoo.bar这个 getter 从激活两次变为一次反向修复则相反。两者都可能改变程序行为因此一律不自动修复仅报告。toString()调用次数计算属性名是非字面量表达式时如foo[bar]、this[foo]修复会改变bar/foo的toString()调用次数只有属性是字面量如foo[5]时才安全修复。注释保留always模式下如果与二元运算符之间、或左操作数与运算符之间存在注释修复会删除注释此时返回null放弃修复never模式下若修复会重复注释同样放弃。测试中/*1*/x/*2*/./*3*/y/*4*/ x.y /*5*/z/*6*/./*7*/w/*8*/;这类注释密集代码也有专门用例验证注释被完整保留。可选链(obj?.a).b (obj?.a).b y、obj.a obj?.a b会被报告但不修复见 tests/lib/rules/operator-assignment.js 末尾的 Optional chaining 分组。与其他规则的关联逻辑赋值运算符、||、??不在本规则管辖范围内由 logical-assignment-operators 规则单独处理该文档开篇也明确引用了本规则作为「数学运算简写」的对照。本规则属于suggestion类型文档 frontmatter 中rule_type: suggestion与其他风格类规则一同在 docs/src/rules/ 目录下维护规则注册入口见 lib/rules/index.js 中operator-assignment: () require(./operator-assignment)。When Not To Use It使用赋值运算符简写本质上是一种风格选择。如果你的团队希望由开发者按具体情况自行决定哪种写法更易读可以关闭本规则不配置该规则即可ESLint 便不会对此施加任何约束。【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考