zoukankan      html  css  js  c++  java
  • 用几个demo帮助理解JS作用域链和声明前置(转载)

    声明前置

    • 变量的声明前置:指在变量被定义时,会在代码执行之前将变量放在最前面进行初始化。
    • 函数的声明前置:会将函数声明放在代码执行之前先去生成该函数,所以函数声明受到函数提升机制的影响,所以无论放在什么位置都可以被调用。

    作用域

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

    作用域链查找过程伪代码

    1. 分析代码,首先可根据提升机制将变量或者函数编译在最前面;
    2. 写出作用域链查找过程伪代码,找到每个作用域的AO、Scope;
    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 
    2. 函数声明放在任何位置都会函数声明前置,而函数表达式只有在这个表达式执行完后才会调用改函数
          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(){..}

    3.     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

    4.     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

    5.     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
      

      作者:饥人谷fanlelee
      链接:https://www.jianshu.com/p/9346423613a0

  • 相关阅读:
    LeetCode 40. 组合总和 II(Combination Sum II)
    LeetCode 129. 求根到叶子节点数字之和(Sum Root to Leaf Numbers)
    LeetCode 60. 第k个排列(Permutation Sequence)
    LeetCode 47. 全排列 II(Permutations II)
    LeetCode 46. 全排列(Permutations)
    LeetCode 93. 复原IP地址(Restore IP Addresses)
    LeetCode 98. 验证二叉搜索树(Validate Binary Search Tree)
    LeetCode 59. 螺旋矩阵 II(Spiral Matrix II)
    一重指针和二重指针
    指针的意义
  • 原文地址:https://www.cnblogs.com/liontone/p/12313223.html
Copyright © 2011-2022 走看看