JavaScript 中的预解析、变量提升与函数提升?

344 阅读1分钟

1.预解析

JavaScript 中代码的执行是由浏览器中 JavaScript 解析器来执行的。JavaScript 解析器执行 JavaScript 代码的时候,分为两个过程:预解析过程和代码执行过程。

预解析过程

  1. 把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值
  2. 把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用
  3. 先提升 函数声明,再提升变量声明

2.变量提升

定义变量时,变量的声明会被提升到作用域的最上面,变量的赋值不会提升

<script>
        console.log(a)//undefined
        var a = 10

        num = 6
        console.log(num, '2')//6
        var num
</script>

以上代码编译后的代码结构可以看做如下运行顺序

<script>
        var a
        console.log(a)//undefined
        a = 10

        var num
        num = 6
        console.log(num, '2')//6
 </script>

3.函数提升

  1. JavaScript 解析器首先会把当前作用域的函数声明提前到整个作用域的最前面
  2. 函数提升只会提升函数声明式写法,函数表达式的写法不存在函数提升
  3. 函数提升的优先级大于变量提升的优先级,即函数提升在变量提升之上
<script>
        fn1()
        fn2()
        function fn1() {
            console.log('fn1')//fn1
        }

        var fn2 = function () {
            console.log('fn2')//Uncaught TypeError: fn2 is not a function
        }
</script>

以上代码编译后的代码结构可以看做如下运行顺序

<script>
        function fn1() {
            console.log('fn1')//fn1
        }
        fn1()
        fn2()
        var fn2 = function () {
            console.log('fn2')//Uncaught TypeError: fn2 is not a function
        }
 </script>

4.变量提升与函数提升综合示例

<script>
        var a = 1
        function fn() {
            a = 10
            console.log(a)//10
            return
            function a() {
            }
        }
        fn()
        console.log(a)//1
    </script>

以上代码编译后的代码结构可以看做如下运行顺序

<script>
        var a = 1
        function fn() {
            var a = function () { }
            a = 10
            console.log(a)//10
            return
        }
        fn()
        console.log(a)//1
    </script>

注意:ES6 新增了 let 和 const 关键字,使得 js 也有了块级作用域,而且使用 let 和 const 声明的变量和函数式不存在提升现象的。呃呃呃,是不是学了个寂寞~