js作用域和预编译

270 阅读2分钟

js作用域和预编译

简单理解:一般理解为变量的作用范围

  1. 全局作用域
    1. 全局作用域在页面打开时被创建,页面关闭时被销毁
    2. 编写在script标签中的的变量和函数,在页面任意位置都可以访问到,此时作为全局作用域
    3. 全局作用域中有全局对象window,代表浏览器窗口,由浏览器创建
    4. 全局作用域中声明的变量和函数做为window对象的属性和方法保存
  2. 函数作用域
    1. 当调用函数时,函数作用域被创建,函数执行完毕,函数作用域被销毁
    2. 每调用一次函数,都会创建一个新的函数作用域,他们之间是独立的
    3. 在函数作用域中可以访问到全局作用域的变量,在函数外部是无法访问函数作用域内部变量的
    4. 在函数内部访问变量时,先从函数本身的作用域中找,找到就直接用,找不到就会在函数上一级作用域中寻找,一直找到全局

详细理解:

执行期的上下文:
  • 函数代码执行前期,会创建一个执行上下文的内部对象AO(函数作用域)
  • 这个内部的对象是预编译时创建出来的,因为函数被调用时,会先进行预编译
  • 在全局执行代码行的前期会创建一个执行期的上下文对象GO(全局作用域)
函数预编译的过程:
  1. 创建AO对象
  2. 找形参和变量声明,将形参和变量名作为AO对象的属性名,值初始为undefined
  3. 实参形参统一
  4. 在函数体里找函数声明,值赋予函数体
例题(案例是从前端斌哥视频看的,解释的很详细):
    function fn(a, c){
        console.log(a);
        var a = 123;
        console.log(a);
        console.log(c);
        function a(){};
        if(false){
            var d = 678
        };
        console.log(d);
        console.log(b);
        var b = function(){};
        console.log(b);
        function c(){};
        console.log(c);
    };
    fn(1, 2)
过程:
    // 1.创建AO对象
    AO: {
        // 2.找形参和变量声明,将形参和变量名作为AO对象的属性名,值默认undefined
        a: undefined
        c: undefined
        d: undefined
        b: undefined
    }
    AO: {
        // 3.实参形参统一
        a: 1
        c: 2
        d: undefined
        b: undefined
    }
    AO: {
        // 4.在函数体里找函数声明,值赋予函数体,注意的是函数声明和函数表达式赋值不是一回事
        a: function a(){};
        c: function c(){};
        d: undefined
        b: undefined
     }
此时预编译完成,AO作用域已形成,可以进行下一步的代码执行。
    function fn(a, c){
        console.log(a);     // function a(){};
        var a = 123;        // AO对象中的属性a的值被改===》123
        console.log(a);     // 123
        console.log(c);     // function c(){};
        function a(){};
        if(false){
            var d = 678
        };
        console.log(d);     // undefined
        console.log(b);     // undefined
        var b = function(){};  // AO对象中的属性b的值被改===》function(){};
        console.log(b);     // function(){};
        function c(){};
        console.log(c);     // function c(){};
    };
    fn(1, 2)