二、预解析(预编译)

93 阅读1分钟

javaScript在执行代码时会分为两个阶段执行。

阶段一:预解析(预编译)
阶段二:在预解析结束后,代码按照从上到下的顺序依次执行。

首先,我们来看看在预解析期间,JS做了什么。

在预解析阶段,会对定义的变量(也就是加var的变量)以及函数Function进行提升。
但是这里需要注意的是,提升var变量只是对声明进行提升,并没有赋值。但是对函数的提升,不仅仅是声明,还有赋值。

练习一下:

<script>
    console.log(a)
    var a = 100
    console.log(a)
    
    在这里,由于JS在预解析阶段会对定义的变量的声明进行提升(并没有赋值)。所以上面的输出语句会打印出undefined
    下面的输出语句则会正常打印出 100
    
    实际上经过处理的代码会是这样:
        var a
        console.log(a) // undefined
        a = 100
        console.log(a) // 100
</script>

再来看另外一个练习:

<script>
    fn() // 1
    function fn(){
        console.log(1)
    }
    
    这里在最上面是可以直接调用fn函数的,因为JS在处理的时候会对函数整体进行提升。(包括声明和赋值)
    
    实际上经过处理后是这样的:
    function fn(){
        console.log(1)
    }
    fn()
</script>

继续下一个练习:

<script>
    gn()
    var gn = function (){
        console.log(1)
    }
    
    这个时候,就会报错:gn is not a function。因为在定义gn时加上了var,导致JS只会对gn的声明进行提升
    并不会对赋值进行提升。
    
    实际上经过处理后是这样的:
    var gn
    gn() //gn is not a function
    gn = function (){
        console.log(1)
    }
</script>

继续下一个练习:

<script>
    console.log(i) // undefined
    for(var i = 0;i < 10;i++){}
    console.log(i) // 10for循环里定义的i是全局变量,会在执行时对i进行变量提升。所以上面输出语句输出 undefined
    下面的输出语句会输出 10
   
</script>

继续下一个练习:

<script>
    var a = 666
    fn()
    function fn(){
        var b = 777
        console.log(a)
        console.log(b)
        console.log(c)
        var a = 888
        var c = 999
    }
    
    思考一下,上面的代码会怎样输出。
    答案是:undefined 777 undefined
    在函数体内的变量,会提升到函数体的最上方。
    并且在寻找变量时,如果全局变量以及函数体内有相同命名的变量,会优先使用函数体内的变量,所以这里的a使用的是函数体内的a。
    经过处理后,代码就会变成下面这样:
    function fn(){
        var b
        b = 777
        var a
        var c 
        console.log(a) // undefined
        console.log(b) // 777
        console.log(c) // undefined
        a = 888
        c = 999
    }
</script>

继续下一个练习:

console.log(a)
a = 555
console.log(a)

此时最上方输出语句会报错,因为定义a没有加var,所以没有进行变量提升,会提示 a is not defined。报错后,后续的代码不会继续执行。

继续下一个练习:

function fn(){
    a = 1 
}

fn()
console.log(a) // 1

之所以会输出a = 1,是因为此时的a是全局变量。
注意:所有没有加var的变量,都是全局变量。全局变量在函数内外都可以访问。