美文网首页
js深刻理解--解析与执行过程

js深刻理解--解析与执行过程

作者: 朝西的生活 | 来源:发表于2019-04-09 22:34 被阅读0次

    全局预处理阶段

    在js代码真正执行之前, 编译器会先对代码执行预处理, 看下面例子

    
    console.log(a); // undefined
    console.log(b); // ReferenceError: b is not defined
    console.log(c); // undefined
    console.log(d); // Function
    
    var a = 1;
    b = 2;
    var c = () => {
      alert(1);
    }
    function d(){
      alert(2);
    }
    

    可以看到, 上面结果实际与我们预期差距很大, 那么编译器是如何进行js的预处理的呢

    1. 创建词法作用域(可以理解为一个js代码执行前就存在的全局变量)
    2. 扫描全局作用域下所有使用 var 关键字声明的变量, 将其赋值为 undefined;
    3. 扫描全局作用域下所有使用 函数声明 方式声明的函数, 并将其赋值为对该函数的引用

    这一操作被称为 声明提前 或者 声明前置 全局的预处理完成后, js代码开始正常执行

    这里面还是有很坑的地方

    • letconst 声明的变量不会被前置
    console.log(a); // ReferenceError: b is not defined
    const a = 1;
    
    • 预处理阶段只会处理全局作用域下的变量声明和函数声明
    var a = 1;
    function b(){
      var c = 2;
    }
    
    // 此时的GO对象
    {
      a: undefined,
      b: Function
    }
    // b函数内声明的c变量没有被预处理
    
    • 只有声明的方式声明的函数才会被前置
    a(); // 1
    b(); // ReferenceError: b is not defined
    c(); // ReferenceError: b is not defined
    d(); // ReferenceError: b is not defined
    e(); // ReferenceError: b is not defined
    f(); // ReferenceError: b is not defined
    
    function a(){
      console.log(1);
    }
    const b = function(){
      console.log(2);
    }
    
    (function c(){
      console.log(3);
    })();
    
    const d = new Function('console.log(4)');
    
    • 遇到声明冲突时, 若为函数则覆盖, 若为变量则跳过
    a(); // 2
    console.log(b); // undefined
    function a(){
      console.log(1);
    }
    function a(){
      console.log(2);
    }
    
    var b = 3;
    var b = 4;
    
    • 不安全的 typeof
      typeof 除了用来检测目标类型之外还有检测变量是否被声明的作用
    // a未声明, undefined, 不会报错
    if (typeof a !== 'undefined'){
      // do something
    }
    

    但是当es6的块级作用于出现之后, typeof也不安全了

    typeof a; // ReferenceError: a is not defined
    let a = 1;
    

    函数预处理阶段

    我们知道, 在块级作用域出现之前, js一直都是函数作用域, 类似的, 函数在真正执行之前也会经历一个预处理阶段

    1. 创建一个AO对象
    2. 找出函数形参以及函数作用域内的变量声明, 并赋值为undefined
    3. 将形参与实参的值相统一
    4. 找出作用域内所有的函数声明, 复制为其函数的引用

    与全局预处理不同, 函数的预处理阶段多了对函数参数的处理

    相关文章

      网友评论

          本文标题:js深刻理解--解析与执行过程

          本文链接:https://www.haomeiwen.com/subject/khswiqtx.html