zoukankan      html  css  js  c++  java
  • javascript闭包

    在javascript中变量有全局作用域和局部作用域。通常,函数内部可以访问全局变量,也可以访问用var声明的局部变量,但是在函数外部不能访问函数内部的局部变量。那么,有时候我们要访问局部变量,如何访问函数内部的局部变量呢?可以用闭包。通俗的讲,闭包就是函数的返回值是一个函数(不是变量),这个返回的函数引用了外部函数的变量。

     1     function add() {
     2 
     3         arg = arguments;
     4 
     5         var add_number = function() {
     6 
     7             var sum = 0;
     8 
     9             for (var i = 0; i < arg.length; i++) {
    10 
    11                 sum += arg[i];
    12 
    13             }
    14 
    15             return sum;
    16 
    17         }
    18 
    19         return add_number;
    20 
    21     }
    22 
    23   var temp =  add(1, 2, 10)();
    24 
    25     console.info(temp);    //13
    26 
    27     
    28 
    29 console.info(arg);    //[1, 2, 10]

    咦?在函数外面竟然还能访问函数内部的变量arg?这就是闭包的神奇特效。因为add()的返回值是一个函数,再把这个函数赋值给一个全局变量,返回值存储有指向其父函数的地址,所以现在全局变量temp就有指向add函数的变量arg的指针,这个指针被存储在内存中(函数执行结束后没有释放),自然就能够在全局范围内访问局部变量咯。

    特别注意:调用函数,返回的函数中如果引用了外部函数的变量,那么就是地址引用,而不是值的引用,如果引用地址指向的变量变化,那么变量跟着变化。见以下:

     1 function closureArray(){
     2 
     3     var func = new Array();
     4 
     5     for(var i = 0;i < 10;i++){
     6 
     7         func[i] = function(){
     8 
     9             return i;
    10 
    11         }
    12 
    13     }
    14 
    15     return func;
    16 
    17 }
    18 
    19  
    20 
    21 (closureArray())[5](); //10

    为什么得到的结果是10而不是0...9呢,因为闭包内的匿名函数中的arguments对象存储的是外部函数的引用(地址)

    问题又来了,如果我们想返回的是[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]呢,很简单,只需要破坏闭包函数对外部函数的引用就可以了:

     1 function closureArray(){
     2     var func = new Array();
     3     for(var i = 0;i < 10;i++){
     4         func[i] = (function(temp){
     5             return temp;
     6         })(i);    //把对外部的引用复制给一个块级作用域的变量,每次块级作用域执行完成之后,就会释放引用,下一次调用又会重新复制,从而改变地址
     7     }
     8     return func;
     9 }
    10 
    11 var arr = closureArray();
    12 console.info(arr);    //[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    说到这里,又有疑问了,为什么闭包内部引用外部变量存储的是外部函数的引用(而不是值)呢?

    这个就是函数作用域链(scope)的问题了。

  • 相关阅读:
    关于生成并发唯一性流水号的解决方案
    父页面得到<iframe>
    struts2 convention配置中常见配置选项及说明
    Struts2下关于Calendar,date的一些处理
    怎样将用户名和密码保存到Cookie中?【转】
    如何调用用户控件(UserControl)的方法 .
    Struts遍历标签<s:iterator>总结 .
    在事业的开展上保持归零的心态
    这种日子最轻松,这样的人生最快乐
    诚实是人世间最珍贵的宝物,是每个人都应当坚守的伟大情操
  • 原文地址:https://www.cnblogs.com/foolishnoob/p/3770562.html
Copyright © 2011-2022 走看看