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)的问题了。

  • 相关阅读:
    飞思卡尔硬件 调试总结
    芯片散热器
    (028)[技术资料]et99加密狗打开函数的一个小bug
    (027)[技术资料]业余制作Windows图标
    (026)[工具软件]剪切板管理:Ditto
    (025)[系统故障]XP下禁止将串口设备识别成鼠标(转)
    (024)[工具软件]截屏录屏软件FSCapture(转)
    (023) 关于51单片机的A5指令
    (022)[工具软件]图片浏览 JPEGView
    (021)VMWare副虚拟磁盘和子虚拟磁盘id不匹配
  • 原文地址:https://www.cnblogs.com/foolishnoob/p/3770562.html
Copyright © 2011-2022 走看看