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

  • 相关阅读:
    浅析什么是HOOK
    用diff命令生成Patch,用Patch命令打Patch
    Git 协作:Fetch Pull Push Branch Remote Rebase Cherry-pick相关
    apt-get update 101错误解决办法
    Python函数参数中的冒号与箭头
    Python中的多线程编程,线程安全与锁(二)
    使用pdb模块调试Python
    Python中的多线程编程,线程安全与锁(一)
    聊聊Python中的GIL
    Python中的单元测试模块Unittest快速入门
  • 原文地址:https://www.cnblogs.com/liontone/p/12313223.html
Copyright © 2011-2022 走看看