• JavaScript作用域和闭包


    在JavaScript中,作用域是执行代码的上下文。作用域有3种类型:

    1.全局作用域

    2.局部作用域---(又叫函数作用域)

    3.eval作用域

    var foo =0;//全局作用域

    console.log(foo);//输出 0
    var myFunction =function(){
      var foo =1;//局部作用域
      console.log(foo);//输出 1
      
      var myinnerFunction =function(){
        var foo =2;//局部作用域
        console.log(foo);//输出 2
      }();
    }();
    eval('var foo = 3; console.log(foo);');//eval()作用域

    在函数内部使用var定义的代码,其作用域是局部的,且只对该函数的其他表达式是可见的,包括嵌套/子函数中的代码。

    var a = "Hello";//
    (function b() {//只执行函数b()
        alert(a);   //undefined
        var a = "World";
        alert(a); 
    })()
     alert(a); //Hello

    JavaScript没有块作用域

    JavaScript中if(){}、for无法创建作用域

    var foo=1;//foo等于1
    if(true){
        foo =2;//foo等于2
        for (var i=3;i<=5;i++){
            foo=i;
            console.log("nei:"+foo)
        }
         
    }
    console.log("wai:"+foo)
    结果:
    //nei:3 //nei:4 //nei:5 //wai:5

    if条件里面与for循环之后内部的结果在下面console.log("wai:"+foo)打印出来的结果是5,说明JavaScript没有块级作用域,只有函数作用域与全局作用域与eval作用域。

     其他语言里面的块级作用域:由花括号封闭的代码块都有自己的作用域,也就是块级作用域(私有作用域)-----花括号是他们作用域的边界,而js的块级作用域边界是function。详细介绍可参阅http://www.cnblogs.com/fengmiaosen/archive/2011/01/10/1932403.html

     js闭包

    网上有很多种解说,其中有一种比较容易理解的说法:

    js分全局作用域和函数作用域。函数作用域里可以访问到全局,通过一个叫作用域链的东西。但全局怎么访问函数呢?就有人想了在函数里面再写一个函数(闭包),这样把作用域链加长了。就可以在全局访问到函数里的数据了。闭包能访问到父级函数里面的数据说明父级里的数据一直存在内存中(闭包存在的情况下),这就会导致内存一直被占着

    简而言之闭包就是能够读取其他函数内部变量的函数。



    总结:闭包它的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
    var countFromZero =function(){
      var count =0;
      return function(){//调用countFromZero的时候返回嵌套的子函数
        
    return ++count ;//count的作用域链定义在父函数里   } }() countFromZero()//输出1 countFromZero()//输出2 countFromZero()//输出3 变量的值始终保持在内存中不会被立即释放出来,每调用一次countFromZero(),count就会加1,而不是调用外出函数后count立刻被清除
    
    

    注意:由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,必要的时候适当销毁

     闭包 js回收机制

    回收规则如下:

        1.全局变量不会被回收。

        2.局部变量会被回收,也就是函数一旦运行完以后,函数内部的东西都会被销毁。

         3.只要被另外一个作用域所引用就不会被回收

    作用域名字解析顺序 

    javascript中一个名字(name)以四种方式进入作用域(scope),其优先级顺序如下:
    1、语言内置:所有的作用域中都有 this 和 arguments 关键字
    2、形式参数:函数的参数在函数作用域中都是有效的
    3、函数声明:形如function foo() {}
    4、变量声明:形如var bar;

    名字声明的优先级如上所示,也就是说如果一个变量的名字与函数的名字相同,那么函数的名字会覆盖变量的名字,无论其在代码中的顺序如何。但名字的初始化却是按其在代码中书写的顺序进行的,不受以上优先级的影响。看代码:

    (function(){
        var foo;
        console.log(typeof foo); //function
         
        function foo(){}
     
        foo = "foo";
        console.log(typeof foo); //string
    })();

    闭包参考链接

    https://www.zhihu.com/question/34510484/answer/59303912

    http://www.cnblogs.com/uedt/archive/2010/10/28/1863389.html

    http://www.cnblogs.com/liyatang/archive/2011/08/05/2128102.html

  • 相关阅读:
    【疑难系列】 是程序卡住了还是怎么了?
    【疑难系列】 一个看起来是数据库死锁的问题
    求求别再这么用log4x了
    如何动态在spring mvc中增加bean
    java中被各种XXUtil/XXUtils辅助类恶心到了,推荐这种命名方法
    少搞点语法糖,多写点功能
    记一次在java中的日期parse错误
    《自控力》读后感·一
    实现数据权限控制的一种方法
    10个必会的 PyCharm 技巧
  • 原文地址:https://www.cnblogs.com/ruoqiang/p/6008542.html
Copyright © 2020-2023  润新知