当前位置:Web前端 > javascript> 正文

JS闭包的用法

时间:2013-9-26类别:Web前端

JS闭包的用法

JS闭包的用法

一、闭包的概念:

闭包是可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。在编程领域我们可以通俗的说:子函数可以使用父函数中的局部变量,这种行为就叫做闭包!

二、闭包的作用:

在说闭包的作用之前,让我们来先看看下面一段代码:

 

<script type="text/javascript">
    function test1(){
        var i=0;
        function test2(){
            alert(++i);
        }
        return test2;
    }
    var temp = test1();
    temp();
</script>

运行这段代码后,我们发现,弹出窗的结果是:1。

 

三、闭包的价值

  • 闭包的价值在于可以作为函数对象 或者匿名函数,对于类型系统而言这就意味着不仅要表示数据还要表示代码。支持闭包的多数语言都将函数作为第一级对象,就是说这些函数可以存储到变量中、作为参数传递给其他函数,最重要的是能够被函数动态地创建和返回。
  •  
  • 四、闭包的两个特点:

    1、作为一个函数变量的一个引用 - 当函数返回时,其处于激活状态。
    2、一个闭包就是当一个函数返回时,一个没有释放资源的栈区。

    其实上面两点可以合成一点,就是闭包函数返回时,该函数内部变量处于激活状态,函数所在栈区依然保留.

    我们所熟知的主流语言,像C,java等,在函数内部只要执行了return,函数就会返回结果,然后内存中删除该函数所在的区域.生命周期也就停止了.一般的js函数也是这样.但是有闭包特性的js函数有点特殊.


     

    五、闭包的样例

    前面的我大致了解了Javascript闭包是什么,闭包在Javascript是怎么实现的。下面我们通过针对一些例子来帮助大家更加深入的理解闭包

    例子1:闭包中局部变量是引用而非拷贝

  • 
    //因此执行结果应该弹出的667而非666。
    
    function say667() {
        // Local variable that ends up within closure
        var num = 666;
        var sayAlert = function() { alert(num); }
        num++;
        return sayAlert;
    }
    var sayAlert = say667();
    sayAlert()
    
    			
  •  

    例子2:多个函数绑定同一个闭包,因为他们定义在同一个函数内。

  • 
    		
  • 
    function setupSomeGlobals() {
        // Local variable that ends up within closure
        var num = 666;
        // Store some references to functions as global variables
        gAlertNumber = function() { alert(num); }
        gIncreaseNumber = function() { num++; }
        gSetNumber = function(x) { num = x; }
    }
    setupSomeGlobals(); // 为三个全局变量赋值
    gAlertNumber(); //666
    gIncreaseNumber();
    gAlertNumber(); // 667
    gSetNumber(12);//
    gAlertNumber();//12
    
    				
  •  

    例子3:当在一个循环中赋值函数时,这些函数将绑定同样的闭包

  • 
    		
  • 
    //testList的执行结果是弹出item3 undefined窗口三次,因为这三个函数绑定了同一个闭包,而且item的值为最后计算的结果,但是当i跳出循环时i值为4,所以list[4]的结果为undefined.
    
    function buildList(list) {
        var result = [];
        for(var i = 0; i < list.length; i++) {
            var item = 'item'+ list[i];
            result.push( function() {alert(item + ' '+ list[i])} );
        }
        return result;
    }
    function testList() {
        var fnlist = buildList([1,2,3]);
        // using j only to help prevent confusion - could use i
        for(var j = 0; j < fnlist.length; j++) {
            fnlist[j]();
        }
    }
    
    				
  •  

    例子4:外部函数所有局部变量都在闭包内,即使这个变量声明在内部函数定义之后。

  • 
    		
  • 
    //执行结果是弹出”Hello Alice”的窗口。即使局部变量声明在函数sayAlert之后,局部变量仍然可以被访问到。
    
    function sayAlice() {
        var sayAlert = function() { alert(alice); }
        // Local variable that ends up within closure
        var alice = 'Hello Alice';
        return sayAlert;
    }
    var helloAlice=sayAlice();
    helloAlice();
    
    				
  •  

    例子5:每次函数调用的时候创建一个新的闭包

  • 
    	
  • 
    function newClosure(someNum, someRef) {
        // Local variables that end up within closure
        var num = someNum;
        var anArray = [1,2,3];
        var ref = someRef;
        return function(x) {
            num += x;
            anArray.push(num);
            alert('num: '+ num +
            '\\nanArray '+ anArray.toString() +
            '\\nref.someVar '+ ref.someVar);
        }
    }
    closure1=new Closure(40,{someVar:'closure 1'});
    closure2=new Closure(1000,{someVar:'closure 2'});
    closure1(5); // num:45 anArray[1,2,3,45] ref:'someVar closure1'
    closure2(-10);// num:990 anArray[1,2,3,990] ref:'someVar closure2'
    
    			
  •  

    六、使用闭包的注意点

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

    2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

     

    七、好了,总结下


    1,闭包外层是个函数.
    2,闭包内部都有函数.
    3,闭包会return内部函数.
    4,闭包返回的函数内部不能有return.(因为这样就真的结束了)
    5,执行闭包后,闭包内部变量会存在,而闭包内部函数的内部变量不会存在.
     

    标签:
    上一篇下一篇

    猜您喜欢

    热门推荐