首页 > 代码库 > js中的闭包

js中的闭包

  对于没有接触过闭包的初学者来说,很难见名知义马上理解什么是闭包。所以首先我们要明确一下什么是闭包。我们先来看一下官方对于闭包的解释所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。看了这个官方的解释,大家对于闭包理解了吗?反正当我看到这个解释的时候是一脸蒙逼,不知道这说的是些什么鬼。因为看到这个解释我很难把闭包和我平时在js中进行的一些操作联系到一起更谈不上学会应用闭包了。可以说闭包是js中的一个难点,难就难在它很抽象。虽然对这个官方的解释我们做不到完全理解,但是我们却可以从中获得一个关键性信息,那就是闭包通常情况下是一个函数。既然是函数那我们就先说一下由关于函数中变量的作用域问题。

1.变量的作用域

  变量无非就分全局变量局部变量两种。

  全局变量:在函数外部定义的变量叫全局变量;全局变量在函数内外都可以被访问。

  局部变量:在函数内部定义的变量叫局部变量;局部变量只在函数内部起作用,在函数外部访问不到。

   下面我将用代码演示一下全局变量和局部变量的区别。

<script type="text/javascript">
    var num = 1;
    function first(){
        alert(num);
    }
    first();//执行这个函数
  alert(num);
</script>

 num在函数外部声明,所以是全局变量。这段代码的运行结果是弹出两次1;由此可见全局变量在函数内部是可以访问到的。

<script type="text/javascript">
    function first(){
        var num = 1;    
    }
    first();
    alert(num);
</script>    

  num在函数内部声明,所以是局部变量。这段代码的运行结果是报错:num is not defined;由此可见局部变量在函数外部是访问不到的。

2.如何在函数外部获取函数内部的变量值

  在很多情况下虽然是在函数内部定义的变量但是在函数外部我们仍然需要调用它,此时应该怎么办呢?我们可以通过下面的方式实现;

<script type="text/javascript">
    function first(){
        var num = 1;    
    function func(){
        alert(num);
    }
    return func;
    }
    var f1 = first();  //调用函数
    console.log(f1); //打印f1
</script>        

  打印的结果是:function fun(){alert(num)};也就是说此时的f1就是func函数。 要想弹出num的值我们可以将上述的f1改为:

    var f1 = first();  
  f1();

  此时运行的结果会弹出num的值1; var f1 = first()时f1代表的是func函数,当 f1()的时候代表执行func函数,所以会弹出num的值。

  那么现在问题来了,我们为什么要这么做呢,首先我们都应该明白一个问题就是定义在函数内部的变量可以被它的子函数访问,而不能在外部直接访问。所以我们需要通过func这个函数来获得num值。

3.何谓闭包

  上面讲了那么多,还没有进入我们今天的主题——闭包。其实我们刚刚已经应用了闭包。上面的func函数就是闭包。是不是感觉有点神奇,不知不觉我们就用了js中的大难点写了个程序。我们可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

4.闭包的用途: 

     上面我们已经提到过了,闭包是将函数内部和函数外部连接起来的一座桥梁。所以它的一个用途就是可以在函数外部获取函数内部的变量值,还有一个作用就是可以将变量存放在内存中;为了帮助大家理解,我写一个案例来说明:

    var nu;
    function first(){
    var num = 1;    
    nu = function func1(){
        num+=10;
    }
    function func(){
        return num;
    }
    return func;
    }
    var f1 = first();  //调用first函数
    var num1 = f1();
    console.log(f1);
    console.log(num1);
    nu();
    var num2 = f1();
    console.log(num2);

我们一起来分析一下这次代码的打印结果:

  1.打印出的f1为function func(){return num},因为first函数的返回值是func,所以f1为函数func;

  2.打印出的num1的值是1。var num1 = f1();这行代码的意思是说执行func函数。所以num1 = func函数的返回值num(1); 

  3.打印出的num2的值是11。  nu()表示的是中间的func1函数的运行,注意我定义的nu是全局变量,如果将func1函数改为var nu = function func1(){num+=10;}直接写nu()就会报错了。

   nu()执行完以后num = 11;此时再执行f1得到的数值是num2 = 11;

注意:使用闭包可以存储变量的值,但是对于计算机来说也会造成负担,所以使用闭包之前都要考虑好这些问题,不可过多使用闭包。

5.测试 

  通过上面的讲解,相信大家对闭包都已经有了一定的了解,接下来让我们用两个小程序来检验一下自己的学习成果吧;

  demo1:

  var sex = "";
  var object = {
    sex : "",
    func : function(){
      return function(){
        return this.name;
      };
    }
  };
  alert(object.func()());

  demo2:

     var sex = "";
  var object = {
    sex : "",
    func : function(){
        var that = this;
      return function(){
        return that.sex;
      };
    }
  };
  alert(object.func()());

 但是要完全搞懂这个代码还需要了解this的用法,可参考http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html;

  

js中的闭包