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”
9
9
9
9
9
9
9
9
9
9
吧,我认为因为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都是最新的值,因为它引用的是外层函数的变量
var j=i;
result[i] = function() {
return j;
};当你定义一个外部变量去保存i的时候,你得到的才会是跟你说的一样,全是9
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楼说的那样了
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的那行取消注释或改成其他值你就明白了。
window.i是不是
var funcs = createFunctions();
for (var i = 0; i < funcs.length; ++i)
document.write(funcs[i]() + "<br />");
这个的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
为什么是window.i?不是应该“JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.”的吗
哪里看得出来不是for中的i,而是window.i?
还有输出的是5个10,那么createFunctions()中的for()有什么用?不是应该每次都输出10个吗?太乱了
不是每次都输出10个,,无论闭包内如何,document.write只在for (var i = 0; i < funcs.length; ++i)
document.write(funcs[i]() + "<br />");这个for循环中调用,也就是说,总共只会输出funcs的长度次数
上面说的其实都是个人的理解方式,我理论方面不行的。反正就是知道你在不使用闭包的前提下return i中的i,它一开始的值就是循环体的总长度,你可以改成return i++;就知道了。这个时候i会执行累加,但基数是从10开始的
2.当去掉()时,就不是调用函数了,而是输出函数
3.活动对象是在函数执行时函数定义的变量
一个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了。
var a,b
function b(){
// 这里你可以操作arg0,arg1,a,b
}
}
闭包的成型条件是:在函数中定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包这里你还需要了解一点垃圾回收,自从java开始,虚拟机就自带了垃圾回收机制。虚拟机会自动释放不在使用的数据内存,但是闭包是个特例。当满足闭包的条件后,它所使用的变量就会被作为全局变量保存起来,有点类似java的static。为什么循环出来的i为10,就是因为你对应的result[index]中其实是一个函数,运用了闭包,但是未执行,它使用到的i,因为已经循环了10次,变成了10.当你给他加上(),自然就返回10了。这里的i就相当于全局变量 for一次就自加了一次可以用firebug跟踪下变量,方便理解。个人浅见,有误处请指正,勿喷
为什么document.write(funcs[i]() + "<br />");会是10?我知道迭代最后i=10,但没有赋值给result[i]啊,因为条件为i < 10为限,不通过啊所以只能i=10;但result[i]却没有被赋值10啊
可以参考
set get属性
返回匿名类
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 />");