本文解析 let ax = bx = 110 这一常见误用:看似同时声明两个块级变量,实则仅 ax 受 let 约束,bx 因无声明关键字而隐式创建为全局变量,导致作用域行为违背直觉。
本文解析 `let ax = bx = 110` 这一常见误用:看似同时声明两个块级变量,实则仅 `ax` 受 `let` 约束,`bx` 因无声明关键字而隐式创建为全局变量,导致作用域行为违背直觉。
在 JavaScript 中,let(以及 const)确实具有严格的块级作用域,但其作用范围仅限于显式使用该关键字声明的标识符。关键在于:赋值操作本身不改变变量的声明方式。
来看原始代码:
function fn() {
let ax = bx = 110; // ⚠️ 危险写法!
ax++;
return ax;
}
fn();
console.log(typeof bx); // "number" —— bx 是全局变量!
console.log(typeof ax); // "undefined" —— ax 仅存在于 fn 块内这段代码的实际执行逻辑等价于:
function fn() {
let ax; // ✅ 块级声明
bx = 110; // ❌ 无关键字 → 尝试赋值给 bx
ax = bx; // ✅ 将全局 bx 的值赋给局部 ax
ax++;
return ax;
}由于 bx 在赋值前未被声明(既无 let、const,也无 var),JavaScript 引擎会在非严格模式下自动将其挂载到全局对象(如浏览器中的 window),即隐式创建全局变量。而在严格模式('use strict')下,此操作会直接抛出 ReferenceError: bx is not defined,从而暴露问题。
立即学习“Java免费学习笔记(深入)”;
✅ 正确做法有多种:
-
显式分别声明(推荐,语义清晰):
function fn() { let ax = 110; let bx = 110; ax++; return ax; } -
解构赋值(一行安全初始化多个 let 变量):
function fn() { let [ax, bx] = [110, 110]; // ✅ 两者均为块级作用域 ax++; return ax; } fn(); console.log(typeof bx); // "undefined" console.log(typeof ax); // "undefined"
⚠️ 注意事项:
- 永远避免 let a = b = value 类型的链式赋值;
- 在所有脚本顶部启用 'use strict',可提前捕获此类隐式全局变量错误;
- var 虽有函数作用域,但同样不支持 var a = b = value 的安全多声明——b 仍会泄漏为全局变量。
总结:let 的块级作用域不会“传染”给未声明的左侧操作数。理解赋值表达式的求值顺序(从右向左)与变量声明的独立性,是写出可维护、无副作用代码的关键基础。


















