
本文详解为何在函数内修改全局变量后,其新值会持续影响全局作用域——关键在于变量唯一性与作用域链查找机制,而非“局部副本”存在。
在 JavaScript 中,let num = 50 声明了一个全局作用域下的块级变量(在模块顶层或浏览器全局对象下),它在整个脚本生命周期中只有一个实例。当箭头函数 logNum 内执行 num = 100 时,并未创建新变量,而是直接更新了这个唯一的全局 num。因此后续 console.log(num) 自然输出 100——这不是“泄漏”或“意外”,而是 JavaScript 作用域规则的准确体现:在当前作用域未声明同名变量时,赋值操作会沿作用域链向上查找并修改最近的可写绑定。
✅ 正确理解的关键点:
- 全局变量 num 是单例,不存在“函数内一份、函数外一份”的副本;
- num = 100 是赋值(assignment),不是声明(declaration);只有 let/const/var 关键字才创建新绑定;
- 若想在函数内隔离变量,必须显式用 let num = ... 重新声明——此时创建的是全新的局部变量,与全局 num 完全无关。
下面对比两种情形:
// 情形一:修改全局变量(原例)
let num = 50;
const logNum = () => {
num = 100; // ✅ 查找并更新全局 num
console.log(num); // 100
};
logNum();
console.log(num); // 100 ← 全局值已改变
// 情形二:声明局部变量(遮蔽全局)
let num = 50;
const logNum = () => {
let num = 50; // ✅ 新建局部 num(遮蔽 global num)
num = 100;
console.log(num); // 100(局部)
};
logNum();
console.log(num); // 50 ← 全局 num 未受影响⚠️ 注意事项:
立即学习“Java免费学习笔记(深入)”;
- 遮蔽(shadowing)全局变量虽可行,但易引发维护困惑,应避免同名命名;
- const 声明的全局变量不可重新赋值,但若其值为对象,属性仍可修改(const obj = {}; obj.prop = 1 合法);
- 在严格模式下,对未声明变量赋值会抛出 ReferenceError,而此处因 num 已声明,故安全。
总结:作用域决定变量可见性,而非值的独立性。只要不重新声明,对全局变量的任何修改都会持久生效——这正是 JavaScript 动态绑定与词法作用域协同工作的自然结果。










