理解Javascript闭包

一、javascript闭包是什么?

      闭包的官方定义是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

      其实通俗来讲就是:闭包就是将函数内部和函数外部连接起来的一座桥梁,通过这个桥梁我们可以读取到一个函数内部的变量,在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”,我们也把这个函数叫闭包。

二、变量的作用域

    变量的作用域有两种:全局变量和局部变量。在Javascript语言中,函数内部可以直接读取全局变量。

列如:

      var x=1;

  function test(){
    alert(x);
  }

  test(); // 1

但是JS在函数外部是无法读取到函数的局部变量

    function test(){
    var x=1;
  }

    test();

  alert(x); // error

三、如何从外部读取一个函数的局部变量

    正常情况下我们是无法直接从外部读取到局部变量的,这时候我们需要通过一种方法来实现我们的想法,闭包应运而生,即在这个函数内部嵌套一个子函数,再将这个子函数返回出来。

    function test(){

    x=1;

    function test2(){
      alert(x);
    }

    return test2;

  }

  var tmp=test();

  tmp(); // 1

四、闭包的用途

    闭包的用途:可以读取函数内部的变量,让这些变量的值始终保持在内存中,防止全局变量污染,私有成员。

function test(){

    var x=1;

    test2=function(){

                x+=1

            }

    function test3(){
      alert(x);
    }

    return test3;

  }

  var tmp=test();

  tmp(); // 2

  test2();

  tmp(); // 3

     在这段代码中,tmp实际上就是闭包test3函数。它一共运行了两次,第一次的值是1,第二次的值是2。这证明了,函数test中的局部变量x一直保存在内存中,并没有在test调用后被自动清除,而原因就在于test是test3的父函数,而test3被赋给了一个全局变量,这导致test3始终在内存中,而test3的存在依赖于test,因此test也始终在内存中,不会在调用结束后,被垃圾回收机制回收。这段代码中“test2=function(){x+=1}”这一行,首先在test2前面没有使用var关键字,因此 test2是一个全局变量,而不是局部变量,其次,test2的值是一个匿名函数,而这个匿名函数本身也是一个闭包,所以test2相当于是return,可以在函数外部对函数内部的局部变量进行操作。

上面代码也可这样书写(模块化)

var tmp=(function(){

    var x=1;

    return function(){

        x+=1;

        alert(x);

    }

})();

tmp();//2

tmp();//3

私有化

 

var tmp=(function(){

    var x=1;

    function test1(){

        x+=1;

        alert(x);

    }

    function test2(){

        x+=1;

        alert(x);

    }

    return{

        a:test1,

        b:test2

    }

})();

tmp.a();//2

tmp.b();//3

五 闭包函数的弊端        

      由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,解决方法是,在退出函数之前,将不使用的局部变量全部清除。

你可能感兴趣的:(理解Javascript闭包)