尧图精选

ESLint no-dupe-keys 规则详解:如何禁止对象字面量中的重复键

🕒 发布时间:2026/9/12 21:20:17 📁 来源:尧图网络
ESLint no-dupe-keys 规则详解如何禁止对象字面量中的重复键【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint对象字面量Object Literal中如果出现多个同名字段JavaScript 运行时只会保留最后一个值其余值被静默覆盖这类问题极难排查。ESLint 的no-dupe-keys规则专门用于在静态分析阶段拦截这类隐患。本文基于 docs/src/rules/no-dupe-keys.md 文档结合 ESLint 仓库中该规则的真实实现lib/rules/no-dupe-keys.js与完整测试集tests/lib/rules/no-dupe-keys.js全面讲解其行为边界、源码原理与在实际项目中的落地方式。读完本文你将理解该规则为何被纳入eslint:recommended推荐配置并掌握它在__proto__、计算属性名、getter/setter 等特殊语法上的精确判定逻辑。规则定位与适用场景no-dupe-keys是一条problem 级问题级规则其目标是在代码提交前发现“必然导致行为异常”的写法而非风格层面的建议。在 lib/rules/no-dupe-keys.js 中规则的元数据明确标注meta.type: problem属于“问题”类别docs.recommended: true被官方推荐配置收录schema: []该规则不接受任何配置选项唯一消息模板为Duplicate key {{name}}.。因为该规则被标记为recommended所以只要项目启用了eslint:recommended预设无需任何额外配置即可生效。在 packages/js/src/configs/eslint-recommended.js 中可以看到它被配置为no-dupe-keys: error。同时规则通过 lib/rules/index.js 注册到 ESLint 内置规则集合中属于“开箱即用”的内置规则。说明该规则的官方文档标注handled_by_typescript: true表示它在处理 TypeScript 语法时同样适用例如对象类型成员、接口成员中的重复键ESLint 在启用 TypeScript 语言支持时依然会执行本规则。规则详情什么算“重复键”规则的核心行为是禁止在对象字面量中出现重复的键名。重复键的典型危害在于代码作者往往期望两个字段共存但运行时后者会覆盖前者造成难以察觉的逻辑错误const foo { bar: baz, bar: qux }; // foo.bar 实际为 qux第一个 baz 被静默覆盖会被判定为错误的代码以下三种形式均会被no-dupe-keys报告为错误/*eslint no-dupe-keys: error*/表示显式开启规则/*eslint no-dupe-keys: error*/ // 完全相同的键名 const foo { bar: baz, bar: qux }; // 引号字符串键与裸标识符键等价 const bar { bar: baz, bar: qux }; // 数字字面量键0x1 与 1 在运行时解析为同一个属性名 const baz { 0x1: baz, 1: qux };关键点在于该规则比较的是键名的字符串值而不是源码的书写形式。bar与bar、0x1与1虽然写法不同但最终都规范化成同一个属性名bar/1因此属于重复键。不会被判定为错误的代码以下写法虽然包含同名键但在 JavaScript 语义中是合法且有意义的规则会放行/*eslint no-dupe-keys: error*/ // 键名各不相同正常通过 const foo { bar: baz, quxx: qux }; // __proto__ 字面键用于设置对象原型计算属性键用于定义普通同名属性二者语义不同 const obj { __proto__: baz, // 设置对象的原型 [__proto__]: qux // 定义一个名为 __proto__ 的普通属性 };配置方式no-dupe-keys没有可配置的选项schema: []因此只能控制它的严重级别无法细调其行为。在eslint.config.js中启用它import js from eslint/js; export default [ js.configs.recommended, // 已包含 no-dupe-keys: error { rules: { no-dupe-keys: error, // 或 warn若希望以警告而非错误呈现 }, }, ];若使用旧版.eslintrc格式则等价于{ rules: { no-dupe-keys: error } }由于规则位于eslint:recommended中绝大多数场景下你不需要手动书写上述配置。源码实现原理以 AST 遍历追踪属性定义从源码层面看lib/rules/no-dupe-keys.js 的核心是一个名为ObjectInfo的辅助类第 24–78 行它以栈式结构跟踪嵌套对象的属性定义状态每当进入一个ObjectExpression节点就基于外层ObjectInfo创建新的实例第 106–108 行当离开该节点时恢复为外层信息第 109–111 行每个ObjectInfo内部使用Map保存“属性名 → { get, set }”记录用于区分普通属性和访问器属性第 32 行。规则对每个Property节点的判定流程第 113–162 行可以概括为四步跳过解构语法若属性的父节点不是ObjectExpression即属于解构赋值var {a, a} obj直接返回。测试用例var {a, a} obj在valid列表中印证了解构模式中的同名绑定不在本规则管辖范围跳过动态键名通过astUtils.getStaticPropertyName(node)提取静态属性名若为null键名无法在静态分析阶段确定如[a]、[f()]直接返回。测试用例var x { [a]: 1, [a]: 2 };属于valid说明两个相同的动态计算键并不会被本规则报告因为它们的值在运行前不可确定跳过__proto__原型设置器当键名为__proto__、kind 为init且既不是计算属性、也不是简写或方法时第 140–148 行视为“设置对象原型”的特殊语法并跳过。这一特判是为了避免干扰普通属性与原型设置两种不同语义查重并上报若该属性名已被定义过info.isPropertyDefined(node)返回true则调用context.report上报错误信息为Duplicate key {{name}}.且定位到重复键的node.key.loc位置第 151–158 行。其中“静态属性名”的提取逻辑定义在 lib/rules/utils/ast-utils.js 的getStaticPropertyName对于非计算属性的Identifier键直接取其name其余情况字符串字面量、数字字面量、模板字符串等则通过getStaticStringValue规范化成字符串。这正是0x1与1、1_0与1数字分隔符能被识别为同一键名的原因。getter/setter 与__proto__的边界处理ObjectInfo的get/set标记第 54–77 行实现了两个重要行为一个键同时拥有 getter 和 setter 是合法的{ get a() {}, set a(value) {} }属于valid因为访问器对中get与set各有独立标记互不冲突getter/setter 与普通属性不能共存{ a: 1, get a() {} }、{ a: 1, set a(value) {} }均被判定为重复键见测试的invalid列表。对于__proto__键规则在合法与非法之间划出了清晰界限代码形式判定原因{ __proto__: null, [__proto__]: null }合法前者设置原型后者定义普通属性{ [__proto__]: null, [__proto__]: null }重复键两个都是普通属性{ [__proto__]: null, __proto__ }重复键简写属性也是普通属性{ [__proto__]: null, get __proto__() {} }重复键访问器属性与普通属性冲突{ __proto__: null, __proto__() {} }合法方法与原型设置器语义不同这些边界场景在 tests/lib/rules/no-dupe-keys.js 中均有对应的valid/invalid测试用例第 27–337 行覆盖了 ES5 到 ES2021 的语法包括八进制数字键012与12、二进制0b1、八进制0o1、BigInt1n、数字分隔符1_0、空字符串键以及含命名捕获组的正则字面量键等。常见边界案例速查综合官方文档与测试用例以下边界写法值得特别留意// 数字键的多种等价写法都会触发规则 var x { 012: 1, 10: 2 }; // 错误八进制 012 与十进制 10 等价 var x { 0b1: 1, 1: 2 }; // 错误ES6二进制 0b1 与 1 等价 var x { 1n: 1, 1: 2 }; // 错误ES2020BigInt 1n 与 1 等价 var x { 1_0: 1, 10: 2 }; // 错误ES2021数字分隔符不改变数值 // 空字符串也是可重复的键 var x { : 1, : 2 }; // 错误 // 两个不同的动态计算键不触发规则 var x { [a]: 1, [a]: 2 }; // 合法无法静态确认键名是否相同 // 展开运算符不会触发规则 var x { a: b, ...c }; // 合法...c 的内容在静态分析时未知 // 嵌套对象互不影响 var x { a: 1, b: { a: 2 } }; // 合法内层 a 与外层 a 属于不同对象总结与最佳实践no-dupe-keys是 ESLint 中一条“小而精”的 problem 级规则它没有选项、逻辑直观却能在重复键静默覆盖数据这一高频隐患上提供可靠防线。使用时只需记住以下几点优先依赖eslint:recommended该规则默认以error级别开启无需手动配置键名比较基于字符串值书写形式引号、十六进制、八进制、BigInt、数字分隔符不影响判定动态计算键、解构模式、__proto__原型设置器会被安全放行不会产生误报getter/setter 对是唯一允许同名键的特例普通属性与访问器属性混用同一键名仍会被报告。如需查看规则在更复杂语法下的判定行为可直接阅读 tests/lib/rules/no-dupe-keys.js 中的 37 组valid用例与 17 组invalid用例想了解同类“重复定义”检查还可参考规则家族中的no-dupe-args、no-dupe-class-members、no-dupe-else-if等相邻规则均位于 lib/rules 目录下。【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →