本文深入解析 JavaScript 引擎在执行代码前的预解释过程,重点对比 var 声明变量与 function 定义函数在预解释阶段的差异。通过代码示例说明变量初始化为 undefined 与函数完整定义的机制,并探讨条件语句中预解释的“无视”特性及重复声明的处理规则,帮助开发者理解变量提升原理以规避常见错误。
带 var 关键字的预解释行为
带 var 关键字的预解释行为
首先观察以下代码的执行结果:
代码如下:
alert(n); // 弹出 undefined
var n = 10;
上述代码弹出的结果是 undefined,而非预期的 10。为了进一步探究原因,我们查看另一段代码的执行结果:
代码如下:
alert(n);
n = 10;
运行时报错如下:

此次报错的原因是代码运行时未声明变量 n。通过对比这两段代码,我们可以发现使用 var 关键字与不使用 var 关键字声明变量存在显著差异。使用 var 声明的变量在代码执行前,浏览器引擎似乎已为其分配了初始值 undefined。因此,我们将代码执行前浏览器引擎自动扫描使用 var 关键字和 function 关键字(后续章节将详细讨论)声明的变量及定义函数的过程,称为预解释。
带 function 关键字的预解释行为
带 function 关键字的预解释行为
观察以下代码的执行结果:
代码如下:
fn(); // 弹出 hello
function fn() {
alert('hello');
}
执行结果弹出 hello,fn 能够正常执行。这是因为在代码执行前,fn 已被预解释,且在预解释阶段已完成定义(defined)。这引出了另一个疑问:为何第一段代码不弹出 10 而是 undefined?这涉及 JavaScript 中声明(declare)与定义(defined)的概念区别。
JavaScript 中的声明与定义
JavaScript 中的声明(declare)与定义(defined)
通常我们使用 var 关键字来声明变量,使用 function 关键字来定义函数。然而,function 关键字在声明和定义函数时是同时执行的,而 var 关键字仅能声明变量,不具备定义的功能。
以下是使用 var 关键字声明变量的示例:
代码如下:
var n; // 声明了一个变量 n
var m = 10; // 声明了一个变量 m,并将 10 赋值给它
以下是使用 function 关键字定义函数的示例:
代码如下:
// 定义了一个函数 fn
function fn() {
alert('hello');
}
var 与 function 预解释的区别
带 var 关键字与带 function 关键字预解释的区别
两者的核心区别在于:使用 var 关键字预解释时仅处理声明部分(因其本身不具备定义能力),而使用 function 关键字在预解释时声明和定义同时完成。回顾第一段代码,分析如下:

条件语句中的预解释特性
看似“无节操”的预解释行为
为何称其“无节操”,请看以下代码(Firefox 浏览器除外):
代码如下:
alert(n);
fn();
if(false) {
var n = 10;
function fn() {
alert('hello');
}
}
第一行代码执行会弹出 undefined,第二行代码执行会弹出 hello。这是因为 n 和 fn 在代码执行前已被预解释,即使 if 条件判断为 false,执着的浏览器引擎仍会将带 var 关键字声明的变量 n 和带 function 关键字定义的 fn 扫描并处理。
重复声明与定义的预解释规则
* 预解释忽略重新声明,但不忽略重新定义
此处逻辑相对复杂且不易理解,故添加星号标记,请分析以下代码:
代码如下:
alert(n);
var n = 10;
var n = 9;
var n;
alert(n);
这段代码的执行结果是什么?我们来逐步分析:

函数重定义的预解释分析
继续上代码,请分析以下执行结果:
代码如下:
fn();
function fn() {
alert('1');
}
fn();
function fn() {
alert('2');
}
fn();代码分析图如下:

带 function 定义的函数预解释分析
总结:
本文通过大量代码和截图概述了 JavaScript 中的预解释机制。纵观各类书籍,对预解释的描述较少,且实际工作场景中直接使用频率不高,遗憾的是它却是各大公司面试题的常客。初接触时,常感觉其不按常理出牌,有时代码看似错误却能正常运行,这增加了其神秘感,也促使我们更深入地理解浏览器引擎解释执行代码的机制。后续博文中,我将结合几道经典案例进行综合分析,再次感谢大家的支持!