Web前端之路让前端飞饥人谷技术博客

用几个demo帮助理解JS作用域链和声明前置

2019-12-07  本文已影响0人  fanlelee

声明前置

作用域

  1. 每当声明一个新的函数就进入一个新的作用域下;
  2. 函数里需要用到的变量(或函数)首先会在自身作用域下找,找不到再逐级向上层作用域去找。

作用域链查找过程伪代码

  1. 分析代码,首先可根据提升机制将变量或者函数编译在最前面;
  2. 写出作用域链查找过程伪代码,找到每个作用域的AOScope
  3. 根据伪代码方可分析出具体结果。

举例说明

  1. 变量的声明前置
    console.log(a);//undefined
    var a = 1;
    console.log(a);//1
    /* 声明前置分析代码 */
    var a
    console.log(a)//undefined
    a = 1
    console.log(a)
    //变量a会声明前置,故第一次输出:undefined
    //第二次输出前变量a已经赋值,故第二次输出:1
  1. 函数声明放在任何位置都会函数声明前置,而函数表达式只有在这个表达式执行完后才会调用改函数
    sayName('world');
    sayAge(10);
    function sayName(name){
        console.log('hello ', name);
    }
    var sayAge = function(age){
        console.log(age);
    };
/* 首先还是根据函数提升机制分析代码 */
    function sayName(){...}
    var sayAge
    sayName('world')   //输出:hello world
    sayAge(10)        //输出:sayAge is not a function
    sayAge = function(){..}
    var x = 10
    bar() 
    function foo() {
      console.log(x)
    }
    function bar(){
      var x = 30
      foo()
    }
/* 首先根据声明前置分析代码 */
    var x
    function foo(){
        console.log(x)
    }
    function bar(){
        var x
        x = 30
        foo()
    }
    x = 10
    bar()

/* 作用域链查找过程伪代码 */
    globalContext{
        AO:{
            x:10
            foo:function
            bar:function
        }
        Scope:{}
    }
    foo[[scope]] = globalContext.AO
    bar[[scope]] = globalContext.AO

    fooContext{
        AO:{}
        Scope:foo[[scope]] = globalContext.AO
    }

    barContext{
        AO:{
            x:30
        }
        Scope:bar[[scope]] = globalContext.AO
    }

//输出: 10
    var x = 10;
    bar() 
    function bar(){
      var x = 30;
      function foo(){
        console.log(x) 
      }
      foo();
    }
/* 作用域链查找过程伪代码 */
    globalContext{
        AO:{
            x:10,
            bar:function
        },
        Scope:{}
    }
    bar[[scope]] = globalContext.AO

    barContext{
        AO:{
            x:30,
            foo:function
        }
        scope:bar[[scope]] = globalContext.AO
    }
    foo[[scope]] = barContext.AO

    fooContext{
        AO:{}
        scope:barContext.AO
    }

    //输出:30
    var a = 1;

    function fn(){
      console.log(a)
      var a = 5
      console.log(a)
      a++
      var a
      fn3()
      fn2()
      console.log(a)

      function fn2(){
        console.log(a)
        a = 20
      }
    }

    function fn3(){
      console.log(a)
      a = 200
    }

    fn()
    console.log(a)
/* 作用域链查找过程伪代码 */
    globalContext{
        AO:{
            a:1->200
            fn:function,
            fn3:function
        },
        Scope:{}
    }
    fn[[scope]] = globalContext.AO
    fn3[[scope]] = globalContext.AO

    fnContext{
        AO:{
            a:5->6->20
            fn2:function
        }
        scope:globalContext.AO
    }
    fn2[[scope]] = fnContext.AO

    fn3Context{
        AO:{}
        scope:globalContext.AO
    }

    fn2Context{
        AO:{}
        scope:fnContext.AO
    }


    //输出: undefined 5 1 6 20 200
上一篇 下一篇

猜你喜欢

热点阅读