
该代码看似同时声明了两个块级变量,实则仅 ax 受 let 约束,bx 因无声明关键字而意外挂载到全局对象(如 window 或 globalThis),导致其在函数外仍可访问——这是易被忽视的赋值链隐式声明陷阱。
该代码看似同时声明了两个块级变量,实则仅 `ax` 受 `let` 约束,`bx` 因无声明关键字而意外挂载到全局对象(如 `window` 或 `globalthis`),导致其在函数外仍可访问——这是易被忽视的赋值链隐式声明陷阱。
在 JavaScript 中,let 和 const 具有严格的块级作用域,但作用域生效的前提是变量必须被显式声明。关键问题出在这一行:
let ax = bx = 110;
它不是并列声明,而是从右向左执行的赋值表达式:
- 首先计算 bx = 110 —— 此时 bx 未被任何 let/const/var 声明,因此 JavaScript 引擎会沿作用域链向上查找;
- 在函数内部找不到 bx 的声明,继续查找到全局作用域,发现也未声明 → 触发“隐式全局变量”行为(非严格模式下),等价于 window.bx = 110(浏览器)或 globalThis.bx = 110(Node.js);
- 然后将该赋值结果 110 赋给由 let 声明的 ax。
因此:
- ax 是块级绑定变量,仅在 fn() 函数内有效,函数执行结束后无法在外部访问;
- bx 实际是全局属性(非全局变量,但具有全局可访问性),故 console.log(typeof bx) 输出 "number";
- 而 console.log(typeof ax) 报错 ReferenceError: ax is not defined(⚠️注意:原问题中输出 "undefined number" 可能因运行环境为非严格模式且存在 var ax 提升干扰,但按标准严格模式或现代执行上下文,此处应直接报错;若实际输出 undefined,说明 ax 在外部根本未声明,typeof 对未声明变量返回 "undefined" 是唯一安全情形)。
✅ 正确写法(推荐):
function fn() {
let ax = 110;
let bx = 110; // 显式声明,各自拥有独立块级作用域
ax++;
return ax;
}
fn();
console.log(typeof bx); // "undefined"(外部不可访问)
console.log(typeof ax); // "undefined"
✅ 一行式安全解构赋值(ES6+):
function fn() {
let [ax, bx] = [110, 110]; // 两个变量均由 let 统一声明
ax++;
return ax;
}
fn();
console.log(typeof bx); // "undefined"
console.log(typeof ax); // "undefined"
⚠️ 注意事项:
- 该陷阱在 var 中同样存在(但 var 会变量提升,行为更隐蔽);
- 严格模式('use strict';)下,bx = 110 会直接抛出 ReferenceError,阻止隐式全局创建,强烈建议始终启用严格模式;
- 工具链(如 ESLint)可通过规则 no-implicit-globals 或 no-unused-vars 辅助识别此类风险。
总结:let ax = bx = value 是危险的语法糖幻觉。真正保障作用域安全的方式,永远是对每个变量使用独立、显式的声明关键字。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











