zoukankan      html  css  js  c++  java
  • javascript的几个知识点scoping,execution context, hoisting, IIFE

     JavaScript 属于解释型语言,JavaScript 的执行分为:解释和执行两个阶段,这两个阶段所做的事并不一样:

    解释阶段:

    • 词法分析
    • 语法分析
    • 作用域规则确定

    执行阶段:

    • 创建执行上下文
    • 执行函数代码
    • 垃圾回收

    Hoisting--提升

    Hoisting的发生范围是函数作用域(function-local scope)。在函数内var定义的变量和函数声名会被提升到该函数作用域的上面。function内的提升的顺序所下:

    1. this, arguments
    2. 形参 formal parameters
    3. 函数声名 function declarations
    4. 变量声名 variable declarations

    举例:

    var a = 1;
    
    function test(){
      if(!a){
      var a = 5;  
     }  
    console.log(a);
    }
    
    test();
    //打印出5这

    这是因为当解析器读到if语句时,发现有一个变量声名和定义:var a = 5;于是解析器就把这个变量的声名:var a;提到当前作用域的顶部。上面的代码最后执行是其实是这样的

    var a = 1;
    
    function test(){
      var a;
      if(!a){
      a = 5;  
     }  
    console.log(a);
    }
    
    test();
    

     如果想打印出1的话,需要用let来定义块级变量: let a =5;或者把var a = 5放到一个立即执行函数里。

    再举一个函数提升的例子

    function test(a){
      if(!a){
       var a = 5;  
     }  
     function a(){}//function declaration
     console.log(a);
    }
    
    test(0);
    //打印出function a(){}

      执行的实际代码如下

    function test(a){
     function a(){}
     var a;
      if(!a){
       a = 5;  
     }  
    
     console.log(a);
    }
    
    test(0);
    //打印出function a(){}
    

      如果代码做以下修改

    function test(a){
      if(a){
       var a = 5;  
     }  
     function a(){}
     console.log(a);
    }
    
    test(0);
    //打印出5

      因为a被重新赋值了。

    function test(a){
      function a(){}
      var a;
      if(a){
       a = 5;  
      }  
     console.log(a);
    }
    
    test(0);
    // if(a)一直是 true,打印出5
    

      

    声名变量var a,只是让解释器知道有这个a的存在,a到底是什么,就需要对变量进行定义:a=5。如果再给a赋值:a = function(){},那a又被定义为了函数。a到底是什么是由定义来决定的。定义的是什么,输出的就是什么。不为因为再次的声名而改变。如果用函数表达式来定义函数,会出现什么情况:

    function test(){
      b();
      var b = function (){}
    }
    test()
    //会报错“undefined is not a function”
    

      函数表达式时,只用变量名被提升,它定义的函数体依然留在原处。执行的代码是这样的

    function test(){
      var b;
      b();
      b = function (){}
    }
    test()
    

     只对b做了声名,而没有定义,所以执行到b()会报错。

    Scoping--作用域

    ES6之前只有函数作用域。ES6加入块级作用域。用let声名的变量是块作用域内有效,用var声名的变量在函数作用域与块作用域里有效。

    作用域链

    作用域内取值是从创建该函数的位置取值,而不是从调用该函数的位置取值。

      https://yq.aliyun.com/articles/693736

    Execution Context 执行上下文

    执行上下文是在执行过程中产生的。

    https://juejin.im/post/59e85eebf265da430d571f89?spm=a2c4e.11153940.blogcont685883.21.727f127e0QVeWU

    作用域和执行上下文之间最大的区别是:
    执行上下文在运行时确定,随时可能改变;作用域在定义时就确定,并且不会改变 

    IIFE(Immediately Invoked Function Expression)

    形式有多种:

    (function(){ cosole.log(1); })()

    (function(){ console.log(1);}())

    +function(){console.log(1);}()

    !function(){console.log(1);}()

    void function(){console.log(1);}()

    这样写是编译不过去的:function(){console.log(1);}()

    顾名思义,immediately invoked function expression,是被解析成为一个函数表达式,然后自执行。

    立即调用函数有个超强的用法,模块模式,如下

    var counter = (function(){
        var i = 0;
        return {
            get: function(){
                return i;
            },
            set: function(val){
                i = val;
            },
            increment: function(){
                return ++i;
            }
        }
        }());
        counter.get();//0
        counter.set(3);
        counter.increment();//4
        counter.increment();//5
    

      想要扩展counter的方法:

    var counter = (function(c){
        c.ext= function (){
            console.log('extend');
        }
         return c;
        }(counter || {}));
    counter.ext();

      

    refer: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.htm

    https://yuiblog.com/blog/2007/06/12/module-pattern/

    http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html

    http://www.cnblogs.com/TomXu/archive/2011/12/30/2288372.htmll

  • 相关阅读:
    MySQL——视图/触发器/事务/存储过程/函数/流程控制
    python连接MySQL/redis/mongoDB数据库的简单整理
    docker安装和使用
    【Python】Django2.0集成Celery4.1详解
    django-haystack全文检索详细教程
    ubuntu16.04安装FastDFS-5.08
    redis之django-redis
    uva 1152 4 Values whose Sum is 0
    2015暑假acm短训小结
    Uva 12569 Planning mobile robot on Tree (EASY Version)
  • 原文地址:https://www.cnblogs.com/Gift/p/10373057.html
Copyright © 2011-2022 走看看