
ESLint 的 no-shadow 规则可有效检测子作用域中重复声明同名变量(即变量遮蔽)的问题,避免因作用域混淆导致的逻辑错误和维护困难。
eslint 的 `no-shadow` 规则可有效检测子作用域中重复声明同名变量(即变量遮蔽)的问题,避免因作用域混淆导致的逻辑错误和维护困难。
在 JavaScript 中,当一个变量在内层作用域(如块级作用域、函数作用域或循环体)中被重新声明,且名称与外层作用域中的变量完全相同时,就会发生 变量遮蔽(variable shadowing)。这种写法虽语法合法,但极易引发理解偏差、调试困难和意外行为——尤其在大型项目或团队协作中。
例如以下代码:
{
const myVar = "ok";
if (true) {
const myVar = "not ok"; // ⚠️ 警告:遮蔽了外层的 myVar
console.log(myVar); // 输出 "not ok"
}
console.log(myVar); // 输出 "ok"
}尽管 myVar 在两个作用域中互不干扰,但语义上存在歧义:读者需反复确认当前引用的是哪一层的变量。更危险的情况出现在使用 var 时(存在变量提升),或在嵌套函数中意外覆盖闭包变量。
此时,ESLint 内置规则 no-shadow 正是为此设计:
✅ 它默认检查所有声明类型(var/let/const/function/class/import)是否遮蔽了外层作用域的变量;
✅ 支持配置 builtin: true 以禁止遮蔽全局内置对象(如 Array、Promise);
✅ 可通过 allow: ["arguments"] 等选项白名单例外场景(谨慎使用)。
启用方式(.eslintrc.js):
module.exports = {
rules: {
"no-shadow": "error",
// 或更严格:禁止遮蔽内置对象
// "no-shadow": ["error", { "builtin": true }]
}
};⚠️ 注意事项:
- no-redeclare 规则仅检测同一作用域内重复声明(如两次 const x = 1;),无法识别跨作用域遮蔽,因此不适用于本例;
- no-shadow 默认不检查函数参数遮蔽(如 function foo(x) { const x = 2; }),若需覆盖此行为,需配合 no-shadow-restricted-names 或自定义配置;
- TypeScript 项目中,建议同时启用 @typescript-eslint/no-shadow(TS 版增强实现),它对类型声明、命名空间等有更精准支持。
总结:为保障代码可读性与可维护性,应主动启用 no-shadow 规则,并将其纳入 CI 流程。遮蔽不是“功能”,而是潜在缺陷的信号——清晰的作用域边界,是健壮 JavaScript 工程实践的重要基石。










