快速理解javascript解析流程

862 阅读2分钟

javascript 执行分两步 1.预解析 2执行 执行的都是解析后的代码

1. 废话不多说,上代码。

console.log(a);
var a = 10
  • 先想想这个执行结果是什么?

js解析完成

    a = undefined
    console.log(a);  // undefined
    a = 10;
  • 执行结果是 undefined 这个过程叫变量提升。解析时遇到var 就会提升上去但并没有赋值。

2. 变形

    console.log(b);
    console.log(c);
    
    function b() {
        console.log("b");
    }
    
    var c = function() {
        console.log("c");
    }

js解析完成

    function b() {
        console.log("b");
    }
    c = undefined;
    console.log(b);  // function b() { console.log("b") }
    console.log(c);  // undefined
    c = function() {
        console.log("c");
    }
  • 同样是函数,带var函数的函数表达式跟定义一个变量都有相同效果。提升并不赋值。 而函数则不同,函数声明会直接提升到顶部。

我们记住两点 在预解析阶段 有函数提升和变量提升两个动作。

3. 继续加强

    (functino(){
        console.log(a);  // undefined
        var a = 10;
    })()
    
    function start(){
        console.log(b);  // function b() { console.log("b") }
        console.log(c);  // undefined
        
        function b() {
            console.log("b");
        }
        
        var c = function() {
            console.log("c");
        }
    }
    start();

变量提升发生在当前的函数作用域内。 自执行函数和函数都有提升过程。

4. 无var的情况

    (function(){
        b = 10;
    })()
    
    console.log(b);

js 解析完成

    (function(){
        b = 10;
    })()
    console.log(b); // 10

没有声明的变量b在解析阶段并没有提升,js执行器在发现b没有在当前作用域声明时会在执行阶段提升到全局。所以外面可以访问到 。 如果在执行阶段提前打印b会直接报错停止运行。

5. 特殊情况

5.1 例1

    (function(){
        console.log(b);       
        var b = 10;
        function b(){
            console.log("fn");
        }
        console.log(b);
    })()

解析完成

    (function(){
        function b(){
            console.log("fn");
        }
        
        console.log(b); // function b(){console.log("fn"); }
        b = 10;
        console.log(b); // 10
    })()

当函数生命和var声明同时存在的时候 函数声明优先级高 这个要注意

5.2 例2

    function start(b){
        start = 10;
        console.log(start);
        console.log(b);
        b = 10;
    }
    start();
    console.log(b);

解析完成

    function start(){
        b = undefined;
        start = 10;
        console.log(start); // function start(b){ ... }
        console.log(b); // undefined
        b = 10;
    }
    start();
    console.log(b); // err b is not defined

在函数内部有参数时 b 就会声明在函数内部。 而给函数名本身赋值是无效的。

结束


还有更多js的解析过程需要大家发现。例如异步代码。setTimeout Promise 等等执行过程 这里列举在函数解析过程当中的常见问题。比如 let const 就没有提升过程。