变量提升是javascript引擎预解析时将var和function声明登记进作用域但不执行赋值或函数体,var声明分预解析(创建变量并赋undefined)和执行(赋值)两阶段,故声明前访问输出undefined;提升范围限于所在作用域;let/const虽提升但受暂时性死区限制,提前访问报错。

变量提升(Hoisting)不是代码被“移动”了,而是 JavaScript 引擎在执行前先做一次预解析:它把 var 声明 和 function 声明 提前“登记”进当前作用域,但只登记声明本身,不执行赋值或函数体运行。
var 声明的预解析本质
用 var a = 10 写代码,引擎实际分两步处理:
- 预解析阶段:仅执行
var a;→ 在作用域中创建变量a,初始值为undefined - 执行阶段:按原位置执行
a = 10;→ 此时才真正赋值
所以 console.log(a) 出现在声明前,输出的是 undefined,而不是报错,因为变量已存在,只是还没赋值。
Java Linux版下载入口,提供 Oracle JDK 26.0.2 官方 Linux 安装包、Java 环境配置、JDBC 数据库连接和 Java 服务端开发相关信息。
作用域决定提升范围
var 声明的提升只发生在它所在的作用域内:
- 全局中用
var声明 → 提升到全局作用域顶部 - 函数内用
var声明 → 提升到该函数作用域顶部,不影响外层 - 块级(如 if、for 内)用
var声明 → 仍属于所在函数或全局作用域,不会被限制在块内
常见误解澄清
这些情况容易误判,但其实都符合预解析逻辑:
-
console.log(a); var a = 1; var a = 2;→ 输出undefined,两次var a在预解析中只算一次声明,后一个赋值覆盖前一个 -
function f() { console.log(b); var b = 3; }→ 输出undefined,b是函数作用域内的变量,被提升到函数顶部 -
console.log(c); c = 5;(没写var)→ 报错ReferenceError,因为这不是声明,而是给未声明变量赋值,不参与预解析
与 let/const 的关键区别
var 的“可访问但值为 undefined”是它的特征;而 let 和 const 虽然也提升,但在声明前访问会直接报错(进入暂时性死区 TDZ),这是设计上的根本不同,不是“提升失效”,而是提升后不允许提前读取。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










