本文详细解析 JavaScript 引擎在执行代码前的预解析(Hoisting)机制。重点阐述 var 声明的变量提升与 function 声明的函数优先原则,并通过四个典型代码案例,展示全局与局部作用域中变量提升的具体表现、未定义值的原因及常见报错场景,帮助开发者规避潜在陷阱。
JavaScript 预解析机制概述
预解析是指在当前作用域内,JavaScript 引擎在正式执行代码之前,会预先处理带有 var 和 function 关键字声明的变量与函数。这一过程会将它们先进行声明,并在内存中分配好位置,随后再按从上至下的顺序逐行解析执行语句。需要注意的是,函数声明的优先级高于变量声明。
接下来通过具体的代码示例来直观展示预解析的行为。
首先看一个标准的预解析案例:
标准预解析与变量提升
var num=10;
fun();
function fun(){
console.log(num);//undefined
var num=20; }
在预解析阶段,变量和函数会被提前声明,具体表现如下:
var num;
function fun(){
var num;
console.log(num);//undefined
num=20;
}
num=10;
fun();
第二种情况涉及函数内部变量的遮蔽效应:
局部变量遮蔽与函数内提升
var num=10;
function dn(){
console.log(num);//undefined
var num=20;
console.log(num);//20
}
dn();
//相当于以下代码
var num;
function dn(){
var num;
console.log(num);
num =20;
console.log(num );
}
num=10;
dn();
第三种情况展示了函数内部变量提升对全局变量的影响:
var a =18;
ss();
function ss(){
var b=9;
console.log(a);//undefined
console.log(b);//9
var a='123';
}
//相当于以下代码
var a;
function ss(){
var b;
var a;
b=9;
console.log(a);
console.log(b);
a='123';
}
a=18;
ss();
第四种情况探讨了连续赋值与变量提升的交互结果:
连续赋值与全局变量访问限制
aa();
console.log(c1);//9
console.log(b1);//9
console.log(a1);//报错
function aa(){
var a1=b1=c1=9;
console.log(a1);//9
console.log(b1);//9
console.log(c1);//9
}
//相当于
function aa(){
var a1=b1=c1=9;//相当于 var a=9;b=9,c=9
var a1;
a1=b1=c1=9;
console.log(a1);
console.log(b1);
console.log(c1)
}
aa();
console.log(c1);
console.log(b1);
console.log(a1);
以上即为 JavaScript 预解析机制的核心内容及相关示例分析。