美文网首页
深入理解JavaScript闭包

深入理解JavaScript闭包

作者: LeeYee11 | 来源:发表于2017-04-17 16:55 被阅读0次

    作用域

    • 变量加var修饰即为局部变量,否则为全局变量
    function foo(){
      a=1
      var b=1;
    }
    foo();
    console.log(a);//1
    console.log(b);//ReferenceError: b is not defined
    
    • 和函数内部的作用域不同,语句块内的作用域相当于全局
    i=999;//全局变量
    function foo(){
      var i=233;//局部变量
      console.log(i);
    }
    foo();//233
    console.log(i);//999
    for(var i=0;i<10;i++){ //此处的i为全局变量i
      console.log(i);//1 2 3 4 5 6 7 8 9
    }
    console.log(i);//10
    
    • 函数内部可以读取到函数外部的变量,但是函数外部的变量不能读取到函数内部的变量
    var a=1;
    function foo(){
      a=2;
      var b=2;
    }
    foo();
    console.log(a);//2
    console.log(b);//ReferenceError: b is not defined
    
    • 函数内部的函数也可能读到函数内部的变量
    function foo(){
      var a=1;
      function bar(){
        console.log(a);
      }
      bar();
    }
    foo(); //1
    
    • 因此可以用函数内部的函数作为返回值来获取函数内部的值
    function foo(){
      var a=2;
      function bar(){
        console.log(a);
      }
      return bar;
    }
    var getResult=foo();
    getResult();
    

    闭包

    • 闭包可以用于获取函数内的局部变量
    function foo(){
      var i=1;
      function getI(){
        return i;
      }
      return getI;
    }
    console.log(i);//undefined
    var GI=foo();
    var i=GI();
    console.log(i);//i
    
    • 闭包可以用于缓存变量
    function foo(){
      var i=1;
      function getI(){
        return ++i;
      }
      return getI;
    }
    var GI=foo();
    var i=GI();
    console.log(i);//2
    i=GI();
    console.log(i);//3
    //说明此处依然是调用的foo的缓存
    //因为getI赋值给了全局变量GI,getI又依赖于foo,所以GI存在时foo就不会
    被回收
    

    总结

    • 闭包可看作保存状态的函数,而该状态对外部是不可见的
    function foo(){
      var i=1;
      return function(a){
        i+=a;
        return i;
      }
    }
    var add=foo();
    console.log(add(0));//1
    console.log(add(5));//6
    
    • 巧用that指向外部变量
    var foo={
      i:1,
      add:function(a){
        that=this;
        return (function(){
          return that.i+a;
        })()
      },
      getI:function(){
        return (function(){
          return this.i;
        )()
      }
    }
    var f=foo;
    console.log(f.add(0));
    console.log(f.getI());
    console.log(f.add(5));
    
    • 用闭包解决异步执行带来的问题
    //一道经典的面试题
    for(var i=0;i<3;i++){
      setTimeout(function(){
        alert(i)
      },2000)
    }
    //实际弹出的是3 3 3,而非0 1 2
    //因为setTimeout()中执行的函数会放置到另一个队列里面执行
    //此时i早已变为3,当alert再执行时,会往上一个作用域中找i
    //此时弹出的就是3 3 3
    
    //解决办法如下
    for(var i=0;i<3;i++){
      (function(e){
        /*** 该作用域的e依赖外层作用域的i ***/
         setTimeout(function(){
           alert(e)
        },2000)
        /*** 作用域结束 ***/
      })(i);
    }
    //构造闭包,使循环赋值给e(即i的引用)
    

    参考

    学习Javascript闭包(Closure)

    相关文章

      网友评论

          本文标题:深入理解JavaScript闭包

          本文链接:https://www.haomeiwen.com/subject/vhvtzttx.html