JavaScript面试题之预解析

423 阅读3分钟

预解析

JavaScript代码是由浏览器中的JavaScript解析器来执行的。JavaScript解析器在运行JavaScript代码的时候分为两步:预解析和代码执行。

  1. 预解析的时候js引擎会把js代码里面所有的var还有function提升到当前作用域的最前面。预解析分为两种:(1)变量预解析(变量提升):就是把所有的变量声明提升到当前作用域的最前面,不提升赋值操作。(2)函数预解析(函数提升):就是把所有函数声明提升到当前作用域的最前面,不调用函数。

  2. 代码执行的时候会按照代码书写的顺序从上往下执行

简单来说就是:js代码执行时会先把所有的声明 varfunction 提升到当前作用域的最前面,而赋值的位置不变,然后从上往下执行。

光用文字描述难以理解,用几个简单的例子更容易快速掌握。

例1:变量预解析

console.log(num);
var num = 10;

以上这段代码的输出结果为:undefined

原因:由于预解析的缘故,var声明的num被提到当前作用域最前面,实际上代码执行的逻辑顺序为:

var num;
console.log(num);
num = 10;

根据代码执行的逻辑顺序,可以知道num输出之前只声明未定义,所以输出结果就是 undefined(未定义)

例2:变量预解析

fun();
var fun = function() {
    console.log(22);
}

以上代码输出结果为:

image.png

报错了,这里又是为什么呢?还是因为预解析。我们再次按照预解析的逻辑,来将逻辑顺序写出来:

var fun;
fun();
fun = function() {
    console.log(22);
}

根据上面预解析之后代码实际的逻辑顺序,我们可以知道在调用函数时fun时,函数fun并未被声明,所以输出结果报错:fun is not a function。所以函数表达式的调用必须写在函数表达式的下面才不会报错。

再来几个案例巩固一下:

例1

var num = 10;
fun();
function fun() {
    console.log(num);
    var num = 20;
}

根据预解析,可以得到代码实际执行顺序为:

var num;
function fun() {
    var num;
    console.log(num);
    num = 20;
 }
 num = 10;
 fun();

所以,输出结果为 undefined

例2

var num = 10;

function fn() {
    console.log(num);
    var num = 20;
    console.log(num);
}
fn();

根据预解析,可以得到代码实际执行顺序为:

var num;
function fn() {
    var num;
    console.log(num);
    num = 20;
    console.log(num);
}
num = 10;
fn();

执行代码,得到的结果为:

image.png

例3

var a = 18;
f1();
function f1() {
    var b = 9;
    console.log(a);
    console.log(b);
    var a ='123';
}

根据预解析,可以得到代码实际执行顺序为:

var a;
function f1() {
    var b;
    var a;
    b = 9;
    console.log(a);
    console.log(b);
    a = '123';
}
a = 18;
f1();

执行代码:得到的结果为:

image.png

例4

f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
    var a = b = c = 9;
    console.log(a);
    console.log(b);
    console.log(c);
}

根据预解析,可以得到代码实际执行顺序为:

function f1() {
    var a;
    a = b = c = 9;//局部变量中未声明直接定义的变量是全局变量。
    console.log(a);//9
    console.log(b);//9
    console.log(c);//9
f1();
console.log(c);//9
console.log(b);//9
console.log(a);//报错
}

执行结果为:

image.png