function createFunctions() {
var result = new Array();

for (var i = 0; i < 10; ++i) {
result[i] = function() {
return i;
};
}

return result;
}var funcs = createFunctions();
for (var i = 0; i < funcs.length; ++i)
document.write(funcs[i]() + "<br />");1、为什么输出为:
10
10
10
10
10
10
10
10
10
102、若document.write(funcs[i]() + "<br />")中的funcs[i]()去掉括号为什么会输出:
function() { return i; }
function() { return i; }
function() { return i; }
function() { return i; }
function() { return i; }
function() { return i; }
function() { return i; }
function() { return i; }
function() { return i; }
function() { return i; }3、而且什么是“活动对象”?原文“每个函数都返回10,因为每个函数的作用域链中都保存着createFunctions()的活动对象,所以它们引用的都是同一个变量i”

解决方案 »

  1.   

    应该输出
    9
    9
    9
    9
    9
    9
    9
    9
    9
    9
    吧,我认为因为for (var i = 0; i < 10; ++i)
      

  2.   

    for (var i = 0; i < 10; ++i) {
            result[i] = function() {
                return i;
            };
        }
    这里面的i其实不是你for中的i,作用域是window,而是window.i,循环的时候都是在更新window.ifuncs[i]()这个是因为你在上面定义的是一个function,去掉括号就不是执行函数了,而是变成了输出函数体本身,因为每一个funcs[i]都是=function() { return i; }。就好比变成了一个字符串变量了闭包就是可以让你每一次得到的i都是最新的值,因为它引用的是外层函数的变量
      

  3.   


    var j=i;
            result[i] = function() {
                return j;
            };当你定义一个外部变量去保存i的时候,你得到的才会是跟你说的一样,全是9
      

  4.   

    function createFunctions() {
        var result = new Array();
        
        for (var i = 0; i < 10; ++i) {
            result[i] = (function(x) {
                return x;
            })(i);
        }
        
        return result;
    }var funcs = createFunctions();
    for (var i = 0; i < funcs.length; ++i)
        document.write(funcs[i] + "<br />");
    改成这样试试
    差不多就是3楼说的那样了
      

  5.   


    function createFunctions() {
        var result = new Array();
        
        for (var i = 0; i < 10; ++i) {
            result[i] = function() {
                return i;
            };
        }
        //i=100;
        return result;
    }var funcs = createFunctions();
    for (var i = 0; i < funcs.length; ++i)
        document.write(funcs[i]() + "<br />");函数createFunctions中i的作用域在createFunctions函数体内,外界是无法访问到的。
    createFunctions生成的函数用到了createFunctions中的变量i,所以createFunctions中生成的函数(funcs数组的项)的作用域链都保存着一个createFunctions的活动对象。
    我们习惯称活动对象为context。
    试着把i=100的那行取消注释或改成其他值你就明白了。
      

  6.   

    那么究竟完整的工作原理是怎么样的?我还是不太了解,觉得好乱啊
    window.i是不是
    var funcs = createFunctions();
    for (var i = 0; i < funcs.length; ++i)
        document.write(funcs[i]() + "<br />");
    这个的i
      

  7.   

    你就这么理解:函数createFunctions有一个活动对象context(实际上它是不可访问的,名称也不是这个),它保存了函数createFunctions的执行环境,包括里面定义的变量result、i和一些其他不明的东西。
    function createFunctions() {
        var result = new Array();
        for (var i = 0; i < 10; ++i) {
            result[i] = function() {
                return i;
            };
        }
        //i=100;
        return result;
    }
    函数createFunctions执行过一次后,其活动对象中result=[function(){return i},……];i=10;
    var funcs = createFunctions();
    在createFunctions外用到createFunctions体内定义的变量时都是引用它活动对象中的变量。
    for (var i = 0; i < funcs.length; ++i)
        document.write(funcs[i]() + "<br />");//funcs[i]用到了createFunctions中定义的变量i
      

  8.   


    为什么是window.i?不是应该“JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.”的吗
      

  9.   


    哪里看得出来不是for中的i,而是window.i?
      

  10.   


    还有输出的是5个10,那么createFunctions()中的for()有什么用?不是应该每次都输出10个吗?太乱了
      

  11.   

    lz应该看下作用域方面的知识,这个闭包用到了外部函数的局部活动对象,而外部函数的局部活动对象中的变量i在外部函数执行完后的值10,当你调用内部函数时,它从外面函数的局部活动对象中得到i=10,所哟就输出10了
      

  12.   


    不是每次都输出10个,,无论闭包内如何,document.write只在for (var i = 0; i < funcs.length; ++i)
      document.write(funcs[i]() + "<br />");这个for循环中调用,也就是说,总共只会输出funcs的长度次数
      

  13.   


    上面说的其实都是个人的理解方式,我理论方面不行的。反正就是知道你在不使用闭包的前提下return i中的i,它一开始的值就是循环体的总长度,你可以改成return i++;就知道了。这个时候i会执行累加,但基数是从10开始的
      

  14.   

    这个i怎么可能是window中的,别误人子弟啊。
      

  15.   

    1.这涉及到递归,因为十个匿名函数都访问了外层函数的变量i,而当执行完函数createFunctions时,这时的i的值是10,所以当调用十个匿名函数时,在匿名函数的作用域链中保存了i这个变量对象,这个变量对象的值是10
    2.当去掉()时,就不是调用函数了,而是输出函数
    3.活动对象是在函数执行时函数定义的变量
      

  16.   

    楼主,这个其实有个比较傻瓜的记忆方法。
    一个Function,如果后面添加了(),其实就是执行匿名函数。
    例如:var A = funciton();这里面,A获得的值就是function中return的返回值。而var A = funciton ;或是var A = funciton(){} ;其实就是将A作为指向函数的指针,因为JS中function就是对象,所以此时显示A的值时,实际显示的是A指向的function的源代码。所以楼主你例子中创建的闭包数组实际就是函数的指针集,如果不加(),显示数组返回的就是闭包函数的源码,加了括号,则执行闭包函数。那为什么显示结果是10呢?这是因为作用域的问题。
    楼主可以在var funcs = createFunctions();这句代码前加上document.write(i + "<br />");
    结果会显示undefine
    因为i只在包含闭包的函数(createFunctions)中有作用,外面for循环中的i与它是互不干涉的。排除了这个影响,我们回顾下之前的代码。
    var funcs = createFunctions();
    这步其实是创建了包含10个函数指针的数组,也就是说,这一步结束i=10。
    而当write funcs[i]()时,函数才会去执行,这时取值i自然就是10了。
      

  17.   

    Update,闭包函数调用的是函数内部的i,外部Write中的i与它互不干涉。建议楼主循环变量不要一直都用i,很容易就搞乱。
      

  18.   

    如果你能理解(),其实就不难了。()代表执行,如果一个函数function(){}少了一个()它就不会执行,当函数体里面没有return时候,它默认的返回值是undefined。常用闭包形式是全局变量,常规的闭包结构function a(arg0,arg1...){
      var a,b
      function b(){
        // 这里你可以操作arg0,arg1,a,b
      }
    }
    闭包的成型条件是:在函数中定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包这里你还需要了解一点垃圾回收,自从java开始,虚拟机就自带了垃圾回收机制。虚拟机会自动释放不在使用的数据内存,但是闭包是个特例。当满足闭包的条件后,它所使用的变量就会被作为全局变量保存起来,有点类似java的static。为什么循环出来的i为10,就是因为你对应的result[index]中其实是一个函数,运用了闭包,但是未执行,它使用到的i,因为已经循环了10次,变成了10.当你给他加上(),自然就返回10了。这里的i就相当于全局变量 for一次就自加了一次可以用firebug跟踪下变量,方便理解。个人浅见,有误处请指正,勿喷
      

  19.   

    哎。始终都不太明白。。
    为什么document.write(funcs[i]() + "<br />");会是10?我知道迭代最后i=10,但没有赋值给result[i]啊,因为条件为i < 10为限,不通过啊所以只能i=10;但result[i]却没有被赋值10啊
      

  20.   

    funcs[i]执行时与匿名函数相关连,保存是匿名函数指针,执行funcs[i]()时,进入到匿名函数中  return i;此时i已经为10啦。也就是说var funcs = createFunctions()函数调用完成时,i=10保留不变。
      

  21.   

    这里的10是i的值,而不是把i=10直接赋值给匿名函数,这里的10之所以是10是因为result[9]返回的是10,result[9]是一个匿名函数,它访问外层函数的i的值,这时的i是result[9]作用域链里保存的变量对象,这个变量i的值是10
      

  22.   

    闭包的概念在面向对象语言中
    可以参考
    set get属性 
    返回匿名类
      

  23.   

    其实,lz的js改成下面这样,就很容易明白了....意思是一样的,只是写法不一样function createFunctions() {
        var result = new Array();
        
        for (var i = 0; i < 10; ++i) {
            //result[i] = function() {
                //return i;
            //};
        }
        result[0] = function() {
             return i;
        };
        //...此处省略8个表达式
        result[9] = function() {
            return i;
        };
        
        return result;
    }var funcs = createFunctions();
    //for (var i = 0; i < funcs.length; ++i)
        //document.write(funcs[i]() + "<br />");
    document.write(funcs[0]() + "<br />");
    //...此处省略8个表达式
    document.write(funcs[9]() + "<br />");