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

  • 相关阅读:
    windwos8.1英文版安装SQL2008 R2中断停止的解决方案
    indwows8.1 英文版64位安装数据库时出现The ENU localization is not supported by this SQL Server media
    Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds
    SQL数据附加问题
    eclipse,myeclipse中集合svn的方法
    JAVA SSH 框架介绍
    SSH框架-相关知识点
    SuperMapRealSpace Heading Tilt Roll的理解
    SuperMap iserver manage不能访问本地目的(IE9)
    Myeclipse中js文件中的乱码处理
  • 原文地址:https://www.cnblogs.com/foolishnoob/p/3770562.html
Copyright © 2011-2022 走看看