变量提升是javascript引擎编译阶段将var和函数声明登记到作用域,非代码移动;var只提升声明赋值仍在原处,函数声明优先且整体提升;let/const存在暂时性死区,访问抛错;建议用let/const、统一声明、避免同名遮蔽。

变量提升(Hoisting)不是代码被“移动”了,而是 JavaScript 引擎在执行前先做了一次编译扫描,把 var 声明 和 函数声明 提前登记到当前作用域里。真正执行时,声明已存在,但赋值还在原处——这就解释了为什么能访问变量却不报错,却拿到 undefined。
var 声明的提升表现
只提升声明,不提升赋值,初始值为 undefined:
- 函数内部用
var声明同名变量,会遮蔽外层变量,哪怕写在console.log后面,前面访问也得到undefined - 全局作用域中,
var a = 10等价于先有var a(顶部),再执行a = 10(原位置) -
var声明的全局变量会自动挂到window上(浏览器环境)
函数声明优先级更高
函数声明会整个提升(包括函数体),且优先于同名的 var 声明:
- 如果同时有
var foo和function foo() {...},函数声明胜出,foo指向函数 - 重复的函数声明会覆盖前面的,以最后一个为准
- 函数表达式(
var bar = function() {...})按var规则处理:只有bar变量被提升,值为undefined,不能提前调用
let/const 的“隐形提升”与暂时性死区
let 和 const 也会提升声明,但不会初始化,从作用域开头到声明语句之间是“暂时性死区(TDZ)”:
- 在 TDZ 内访问变量,直接抛出
ReferenceError,而不是返回undefined - 这其实是更严格的约束,强制开发者按顺序声明再使用
- 块级作用域(如
if、for内)中用let/const,变量只在该块内有效
实用建议:减少陷阱
不用绕开机制,而是用习惯规避问题:
- 函数开头统一声明所有
var变量(即使老项目维护,也建议加注释说明) - 新项目默认用
let/const,避免var的遮蔽和提升混淆 - 避免内外层同名变量,尤其不要在函数内重新声明全局变量名
- 启用严格模式(
"use strict"),它会让一些隐式错误更早暴露
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











