声明提前、预解析、变量提升、函数提升等术语粗略理解的话,其实指代的都是同一事情。
《JavaScript权威指南》中用声明提前代指。“声明提前”这步操作是在JavaScript引擎的“预编译”时进行的,是在代码开始运行之前。
Javascript代码是由浏览器中的JavaScript解析器来解析的,可以认为解析器在解析代码的时候分为两步:预解析(预编译)和代码执行。
一、变量预解析(变量提升)
变量预解析就是指,把所有的变量声明提升到当前作用域的最前面,但不提升赋值操作。
例如:
console.log(a);
var a = 10;
上述代码的执行结果为undefined,它的实际执行顺序可以理解为:
var a;
console.log(a);
a = 10;
二、函数预解析(函数提升)
函数预解析则是把所有的函数声明提升到当前作用域的最前面,但不执行函数。
用function关键字声明的函数遵循函数预解析原则,会将函数的声明提升到作用域最前面。但使用变量接受函数的声明方式,会提升该变量的声明,所以可以认为是变量提升,而变量赋值(接受函数)并没有执行。
例如:
fn();
function fn(){
console.log("a");
}
相当于函数在fn();上面
而:
a();
var a=function(){
console.log("a");
}
上述函数执行时则会报错,a is not a function
上述函数可以理解为:
var a;
a();
a=function(){
console.log("a");
}
三、简易面试题
var a = 1;
function fn1(){
a = 2;
var a;
alert(a);
}
function fn2(){
alert(a);
}
fn1();//2
fn2();//1
上述函数的执行顺序可以认为:
var a;
function fn1(){
var a;
a = 2;
alert(a);
}
function fn2(){
alert(a);
}
a = 1;
fn1();
fn2();