概念:
封闭了外部函数作用域中变量的内部函数,并且返回该内部函数,该变量称为自由变量,也可以叫做闭包变量. 即便返回该外部函数,由于内部函数的间接引用该变量,当GC检查没有相关对象引用它时,就会释放该资源.//(1)
         function (n) {
             alert(n);
         } (3); //没有效果
         //(2)
         (function (n) {
             alert(n);
         })(3); //会弹出3
         //(3)
         var b = function (n) {
             alert(n);
         } (3); //也会弹出3
         //(4)
         var b1 = function (n) {
             alert(n);
         }
         b1(3); //也会弹出3
         /*从上面代码中我可以得出
         1.(1)和(2)的区别在于(1)没有执行,(2)执行啦
         2.()表示让匿名函数立刻执行
         *//*
         通过下面代码Result1和Result2输出的结果分别是什么了.
         结果肯定是不一样的
         Method1:输出的是:1-9
         Method2:输出的是:9个10
         为什么会这样了.
         你可以考虑刚才的开胃小菜中的Demo.
         下面我们来看下Method1中的
         (function (m) {
                     return m;
                 })(i);
         这个匿名函数返回的是经过运算结果的值,然后赋给数组
         接下来我们看下Method2中的
         array[j] = function () {
                     return j;
                 };
            此时数组获取的时该函数的引用,该函数并没有执行
         */
         function CreateArray1() {
             var array = new Array();
             for (var i = 0; i < 10; i++) {
                //区别
                 array[i] = (function (m) {
                     return m;
                 })(i);
             }
             return array;
         }
         var results1 = CreateArray1();
         document.write("Method1 Results:<br/>");
         for (var i = 0; i < results1.length; i++) {
             document.write(results1[i]+"<br/>");
         }
         document.write("------------------------<br/>");
         document.write("Method2  Results:<br/>");
         function CreateArray2() {
             var array = new Array();
             for (var j = 0; j < 10; j++) {
                 //区别
                 array[j] = function () {
                     return j;
                 };
            }
            return array;
        }
        var results2 = CreateArray2();
        for (var i = 0; i < results2.length; i++) {
            document.write(results2[i]() + "<br/>");
        }
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
     <script type="text/javascript">
         /*
            当我点击例子1,例子2,例子3的时候 分别弹出1,2,3
            代码如下:
            但是下面的代码没有得到我想要的效果,而是点击所有的"例子"都是4.
            这个原因就是闭包造成的.每个点击onclick引用的函数都是alert()
            当真个循环结束的时候,alert()函数返回的值是最大值.
            怎么解决这个问题了
            看func2()
            //怎么理解这个话(function (n) { return function () { alert(n) }; })(v);
            立刻执行当前函数,当前例子onclick引用的函数就是function () { alert(n) },n的值就是当前v的值
         */
         function func1() {
             var v;
             for (var i = 1; i < 5; i++) {
                 v = i;
                 document.getElementById('closureExample' + v).onclick = function () { alert(v) };
             }
         }
         function func2() {
             var v;
             for (var i = 1; i < 5; i++) {
                 v = i;
                 document.getElementById('closureExample' + v).onclick = (function (n) { return function () { alert(n) }; })(v);
             }
         }
         window.onload = function () {
             //func1();
             func2();
         }
    </script>
</head>
<body>
<a href="#" id="closureExample1">例子1</a>
<a href="#" id="closureExample2">例子2</a>
<a href="#" id="closureExample3">例子3</a>
<a href="#" id="closureExample4">例子4</a>
</body>
</html>

解决方案 »

  1.   

    BLOG:
    http://blog.csdn.net/ws_hgo/article/details/6892994
      

  2.   

    关于func2也可以写成这样
    <body>
    <a href="#" id="closureExample1">例子1</a>
    <a href="#" id="closureExample2">例子2</a>
    <a href="#" id="closureExample3">例子3</a>
    <a href="#" id="closureExample4">例子4</a>
    <script type="text/javascript">
            function func2() {
                 var aCollection = document.getElementsByTagName("a");
                 for(var i=0;i<aCollection.length;i++){
                    aCollection[i].onclick=(function(n){
                        return function(){alert(n+1);}
                    })(i)
                 }
             }
            func2();
    </script>
    </body>
      

  3.   

    可以不要在设置个func2的内部变量供onclick的内部调用。
      

  4.   


    Thanks
    你和我的代码 没有多大区别 都是一个意思
      

  5.   

    学习,
    (function (n) {
                 alert(n);
             })(3); 函数加()是原型的意思吗?
      

  6.   


    var object={
    function one() {},
    function two() {}
    }
      

  7.   


    直观一下var a ="eeeee"
    a.length"eeeee".length//出错
    ("eeeee").length //木问题
    function aa(){
    alert(1)
    }//我要执行他?
    function aa(){
    alert(1)
    }()//???出错
    (function aa(){
    alert(i)
    })()//木问题总的来说“()”表达式运算
    http://www.cnblogs.com/snandy/archive/2011/03/08/1977112.html
    传送们看下
      

  8.   


    我理解的函数加()表示一个匿名函数指向里面的函数
    (3),传入参数3并调用匿名函数,相当于下面方式的内联写法,只不过直接省去了中间变量
    var b1 = function (n) {
                 alert(n);
    }
    b1(3); 
    声明变量的用法跟C#中的Action<T>使用上是一样的,但C#委托暂时不支持委托的内联调用
      

  9.   


    最后那段代码,func1的理解不对。之所以会出现错误的答案,不是因为闭包,而是没有用闭包造成的。js是运行时绑定。在事件句柄运行的时候,外部循环早就结束。所以会是4。
      

  10.   

    (function($g){
       
       function start1(a){} // 私有方法
       function start2(a){}
       var count = 0; // 私有变量
       var a = {
          start : function(){
             count ++;
             start1();
             start2();
          }
       };   $g.a = a; // 挂到$g上,作用域外访问的唯一途径})(window);我一般这么用 
      

  11.   


    在c#中,this始终指向最外层的类的实例,对吧?
    比如class A{
       private A self = this;
       public void a(){
          object b = new Action(delegate(){
              this.self == this; // 这里的this就是self,对吧
           });
       }
    }
      

  12.   

    <button id="btn">按钮</button>
    var btn = document.getElementById("btn");
    for(var i=0; i<10; i++){
    btn.onclick = function(i){
    return function(){
    alert(i)
    }
    }(i)
    }
    现在是点击按钮是弹出数字9,
    我现在想让每一次点击都让它加1;
    也就是说第一次点击的时候是1;
    也就是说第二次点击的时候是2;
    与此类推...
      

  13.   

    document.write(results2[i]() + "<br/>");这个地方为何是10,求教原因
      

  14.   

      var btn = document.getElementById("btn");
                btn.onclick = (function (v) {
                    return function () {
                        alert(v++);
                    };
                })(1)
      

  15.   

    很多语言都提供了闭包的能力。关于闭包,有一点非常重要,楼主用实例演示却没有给出基本规律:闭包里闭进去的是外面变量本身,而不是外面变量的复制品。
    这意味着,如果发生闭包时的对象 A 在闭包之后又发生了更改(Javascript 总是以引用的方式传值),那么闭包内的对象 A 的值也就同时发生了改变。在循环中这种影响被真正体现出来,就像楼主给的代码的第二段中的 CreateArray2 和 第 23 楼那样
    为了消出这种影响,可以使用楼主给的示例代码中的 CreateArray1 的做法所以,23 楼的朋友没有认真看楼主的贴子。
    顺便说一下,关于闭包,欢迎访问我的博客上关于闭包的文章,阮一峰也写了专门介绍 Javascript 的文章
    最后,注意一下,要正确地使用闭包。不正确的闭包会导致内存泄露、堆栈溢出等问题。
      

  16.   

    JS 必包技术,为什么要发到.net版来
      

  17.   

    闭包得看 jQuery,那里的闭包足够看晕掉
      

  18.   

    闭包函数最关键的是要弄清楚 this 这个东西,this 在 JavaScript 中是很复杂的、很烦!在静态语言中 this 对象是不可变的,而在动态语言 JavaScript 中这个 this 是可变的,正因为可变导致语法会变得很复杂。一般来说,对于诸如 click, mouseover 之类的事件,在给事件绑定事件任务时并不能加上参数,但利用闭包就可以很好地解决这一点。
    /**
     * 为 element 使用 handler 处理程序添加至 event 事件
     * 兼容 IE 及 Firefox 等浏览器
     *
     * 例如为 botton 对象添加 onclick 事件,使用 clickEvent
     * 方法作为处理程序:
     *   Event.addEvent(botton, 'click', clickEvent);
     *
     * @param element  需要添加事件的对象(Object)
     * @param event    需要添加的事件名称(String),不加“on”
     * @param handler  需要添加的方法引用(Function)
     */
    addEvent : function(element, event, handler) {
      if(element.attachEvent) {
        element.attachEvent('on' + event, handler);
      } else if (element.addEventListener) {
        element.addEventListener(event, handler, false);
      } else {
        element['on' + event] = handler;
      }
    },/**
     * 添加事件处理程序时,只能添加一个方法的引用,并不能给
     * 方法加上参数。比如定义了 clickEvent(str) 这个方法,现
     * 在要将其作为 obj 的 onclick 的事件处理程序,就可以用:
     * obj.onclick = Event.getFuntion(null, clickEvent, str);
     */
    getFunction : function(obj, fun) {
      if (!fun) {
        return function(){};
      }
      var args = [];
      obj = obj || window;
      for(var i = 2; i < arguments.length; i++) {
        args.push(arguments[i]);
      }
      return function() {
          fun.apply(obj, args);
        };
    }
      

  19.   


    //(1)
             function (n) {
                 alert(n);
             } (3); //没有效果
             //(2)
             (function (n) {
                 alert(n);
             })(3); //会弹出3
             //(3)
             var b = function (n) {
                 alert(n);
             } (3); //也会弹出3
             //(4)
             var b1 = function (n) {
                 alert(n);
             }
             b1(3); //也会弹出3
             /*从上面代码中我可以得出
             1.(1)和(2)的区别在于(1)没有执行,(2)执行啦
             2.()表示让匿名函数立刻执行
             */
    这个我补充一下真正的原因function (n) {
                 alert(n);
             } (3)
    这个不执行是因为浏览器引擎并不支持这种格式,它不知道
    function (n) {
                 alert(n);
    }
    是一个函数,所以才用()括起来,告诉浏览器,这是一个函数,并且我要执行它但其实不一定用()括起来才可以,我们只要用任意运算符,"~","+","-"等等,告诉浏览器这是一个函数,都可以实现,如
    ~function (n) {
                 alert(n);
             } (3)
    +function (n) {
                 alert(n);
             } (3)
    -function (n) {
                 alert(n);
             } (3)
      

  20.   

    谢谢 你的回复
    有的回复
    function (n) {
      alert(n);
    }
    是一个函数,所以才用()括起来,告诉浏览器,这是一个函数,并且我要执行它
    你这句话 有问题
    此时 只是创建了一个函数 但是 并没有执行它。
    如果换成这样
      (function (n) {
                 alert(n);
             })(3); //会弹出3
    就是创建了一个匿名函数,并且即时执行
      

  21.   

    循环内使用闭包的其实要根据作用域来解释
     首先js中是没有“块状作用域”的,请看下面例子
    //scope1 作用域1
     for (int i = 0; i < 10; i++){
    //scope2 作用域2
      String str = "123";
     
     }  
     Systen.out.print(i);
     Systen.out.print(str);
     
     在有块状作用域的语言中,scope1与scope2是不同的作用域,所以
     Systen.out.print(i);与Systen.out.print(str);都应该报错,i,str未定义
     
     但js并没有块状作用域,看以下例子
    //scope1 作用域1
     for (var i = 0; i < 10; i++){
      //scope2 作用域2
      var str = "123";
     }
       
     alert(i);
     alert(str);  在js中scope1与scope2是同级的,所以alert(i)打印出10, alert(str)打印出123
     不单for是这种情况,if,while等都是一样的,  上面例子等同于

    //scope1 作用域1
     var i = 0;
     var str;
     for (; i < 10; i++){
      //scope2 作用域2
      str = "123";
     }
       
     alert(i);
     alert(str);
     
     所以
     //scope1 作用域1
     var els = document.getElementsByTagName("li");
     for (var i = 0, j = els.length; i < j; i++){
      //scope2 作用域2
      var el = els[i];
    el.onclick = function(){
    //scope3 作用域3
    alert(i);
    }
     }
     其实等同于   //scope1 作用域1
     var els = document.getElementsByTagName("li");
     var i = 0, j = els.length;  for (; i < j; i++){
      //scope2 作用域2
      var el = els[i];
    el.onclick = fn;
     }  function fn(){
    //scope3 作用域3
    alert(i); //当执行onclick时,i已经循环完毕
     }

     这时大家会想,scope3与scope1,scope2是不同一个作用域,为什么还能打印出来,
     这是因为js有作用域链这种思想,当i在scope3找不到的时候,会向上级作用域scope2访问,如果类推,
     直到scope2访问到,所以这里的i其实就是scope1中的i,这时i已经是循环完毕了。
     因此要避免这种情况,我们就要从它的作用域入手了,请看改造例子  //scope1 作用域1
     var els = document.getElementsByTagName("li");
     for (var i = 0, j = els.length; i < j; i++){
      //scope2 作用域2
      var el = els[i];
    el.onclick = function(i){
    //scope3 作用域3
    return function(){
    //scope4 作用域4
    alert(i)
    }
    }(i)
     }  因为作用域链,alert(i)访问scope4没有,向上级scope3访问,它发现i已经由(i)传进来赋值了,
     所以alert(i)这里的i其实是scope3作用域中的i,而并不是scope1中的i  而如果我们改成这样
    //scope1 作用域1
     var els = document.getElementsByTagName("li");
     for (var i = 0, j = els.length; i < j; i++){
      //scope2 作用域2
      var el = els[i];

    el.onclick = function(){ //这里没有声明形参
    //scope3 作用域3
    return function(){
    //scope4 作用域4
    alert(i)
    }
    }(i)
     }  alert(i)中的i访问到的就是scope1的i,打印出来的还是循环完毕后的i...
      

  22.   


    其实我意思是用()包着函数的原理是告诉引擎,这是一个函数,用其他运算符如"~", "+","-"等告诉引擎这是个函数就都可以实现并且我要执行它,这句话是指最后加上()的时候
    +function(n){
      alert(n)
    }(1)“+”是告诉引擎
    function(n){
      alert(n)
    }是一个函数,(1)是执行它
      

  23.   

    ()本身也是个运算符,表示函数的执行。js语法是没有中每行语句的‘;’不是必须的。
    这样写
    function (n) {
                 alert(n);
             }(3)
    是语法错误;如果换成
    function foo(n) {
                 alert(n);
             }(3)
    则没有问题,实际上这相当于
     function foo(n) {
                 alert(n);
             };
    (3);
      

  24.   

    function (n) {
                 alert(n);
             }(3)
    这种写法并不是语法错误,只是引擎解析出来的与我们想做的不同而已,这里引擎认为是没语法问题的
      

  25.   

    我测试过了,确实是语法错误function statement requires a name
    [在此错误处中断] function (n) { 
      

  26.   


    你应该是在谷歌浏览器中测的吧?IE6与FF是没问题的,这是不同宿主引擎的标准不同
      

  27.   

    //(1)
             function (n) {
                 alert(n);
             } (3); //没有效果这个在IE9和FF6中都是不能运行的,是语法错误吧.
      

  28.   

     当我点击例子1,例子2,例子3的时候 分别弹出1,2,3
                代码如下:
                但是下面的代码没有得到我想要的效果,而是点击所有的"例子"都是4.
                这个原因就是闭包造成的.每个点击onclick引用的函数都是alert()
                当真个循环结束的时候,alert()函数返回的值是最大值.
                怎么解决这个问题了
                看func2()
                //怎么理解这个话www.105h.com(function (n) { return function () { alert(n) }; })(v);
                立刻执行当前函数,当前例子onclick引用的函数就是function () { alert(n) },n的值就是当前v的值
             */
             function func1() {
                 var v;
                 for (var i = 1; i < 5; i++) {
                     v = i;
      

  29.   

    (ucType & FH_DII_MASK) & FH_DII_DATA
      

  30.   

    封闭了外部函数作用域中变量的内部函数,并且返回该内部函数,该变量称为自由变量,也可以叫做闭包变量. 即便返回该外部函数,由于内部函数的间接引用该变量,当GC检查没有相关对象引用它时,就会释放该资源.能详细解释下GC不?
      

  31.   

     function (n) {
      alert(n);
      } (3)
    语法错误, 函数声明不能被执行 。
    (function (n) {
      alert(n);
      }) (3)
    ok, 函数声明被括号运算符强制转化成表达式. 可以执行.
      

  32.   

    哥,你这代码书写,太初级了。
    应该搞得专业一些,
    1、看看雅虎34法则中关于js的论述。2、给你几个例子看看: http://my.oschina.net/u/150089/codelist
      

  33.   


    关于JS GC 这块 我没有研究.