var变量提升但赋值不提升,let/const有暂时性死区且块级作用域;循环中var共享绑定而let每次迭代新建绑定;默认用const,需重赋值才用let。

var 声明的变量会“提升”,但赋值不会
声明会被移到作用域顶部,但初始化(即等号右边的值)仍保留在原位置。这意味着 var a = 1 实际上被拆成两步:var a 提升,a = 1 留在原地。
常见错误现象:console.log(a) 输出 undefined 而非报错,即使它写在声明之前。
- 只在函数作用域内有效(不是块级),
if或for里的var仍可在外部访问 - 重复声明同一变量名不会报错,后一次声明会覆盖前一次(但不重新初始化)
- 全局下用
var声明,会成为window的属性(浏览器环境)
let 和 const 是块级作用域,但行为不同
let 和 const 都绑定到最近的块({}),且不存在变量提升——它们有“暂时性死区”(TDZ):从块开始到声明语句执行前,访问会直接抛出 ReferenceError。
关键区别在于可变性:
立即学习“Java免费学习笔记(深入)”;
-
let允许后续重新赋值,但不能在同一作用域重复声明 -
const必须在声明时初始化,且不能重新赋值;注意:它不冻结对象或数组内容,只是不让变量指向新地址 -
const obj = {a: 1}合法,obj.a = 2合法,但obj = {}会报错
var / let / const 在循环中的表现差异明显
这是最容易踩坑的场景之一。用 var 声明的循环变量,在异步回调中往往拿到的是最后一次迭代的值。
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0) // 输出 3、3、3
}
而 let 每次迭代都会创建一个新的绑定:
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0) // 输出 0、1、2
}
- 想在循环里安全捕获当前值,优先用
let -
const在for...of中很自然:for (const item of arr) -
var在现代代码中基本应避免,除非要显式利用函数作用域或变量提升特性(极少见)
默认应该用 const,需要重赋值才用 let
这不是教条,而是基于实际维护成本的判断:越少可变状态,越不容易出错。90% 以上的变量其实不需要重赋值。
例如函数参数、DOM 查询结果、API 返回数据、配置对象——这些通常只需一次赋值,就该用 const。
- 如果明确知道变量后续要改(比如计数器、开关标志、临时缓存),再用
let -
var已被 ES6 标准标记为“遗留特性”,新项目不应出现 - TypeScript 编译器和 ESLint(如
no-var规则)默认会警告var的使用
if 或 for,还出现在 try/catch 的 catch 绑定、模块顶层、甚至 IIFE 外部——const 和 let 的作用域边界比直觉中更细、更严格。











