讲的是闭包的问题 函数的执行环境我明白,闭包感觉有点相似于java中的内部类(不知有错没),书上举了一个下面的例子
function createFunctions(){
var result =new Array();
for(var i=0;i<10;i++){
result[i]=function(){
return i;
};
}
return result;
}
书上说函数会返回一个函数数组 但是每个函数都是返回的10,并非自己的索引。这里不太明白...书上把代码改成了
function createFunctions(){
var result =new Array();
for(var i=0;i<10;i++){
result[i]=function(num){
return function(){
return num;
};
}(i);
}
return result;
}
说这样就能返回索引了... 头晕了(~@.@~)
这确实是讲闭包的一个典型的例子。
闭包不是JS所特有的,很多语言都有。维基百科上对闭包的定义是“闭包是引用了自由变量的函数”。首先闭包是一个函数,另外一个条件是它引用了自由变量(可以理解为该函数自身以外的变量)。
就你这个问题来说,第一个示例代码中返回的一组函数中却是有对变量i
的引用,但是引用的是同一个值i
,而随着循环结束,i
的值最终变成了10
,所以你会输出一堆10
。
而第二个示例代码中,你返回的函数中有一个变量num
,而它是一个自由变量,因为它是其外部函数的一个变量,而不是自身定义的。你实际上返回的是一个闭包。每一次循环都会返回一个新的闭包,所以对于每一个i
值都对应有一个闭包。所以你最终可以输出对应的i
值。
由于在其他面向对象的语言中很少接触到闭包这个概念,所以刚接触闭包的时候可能会觉得有些难以理解,这很正常,多看些资料,时间长了也就慢慢了解了。
另外,闭包和Java中的内部类是有些许相似,但是闭包比前者更加灵活。
参考连接:
- 闭包 (计算机科学)
- Closures
- 学习Javascript闭包(Closure)
闭包又见闭包...LZ你运行一下第一个createFunctions(),看看你得到结果是什么?
[function () { return i }, function () { return i }, function () { return i }, function () { return i }....]
而不是你想象中的
[function () { return 0},function () { return 1 }, function () { return 2 }, function () { return 3}, ....]
醒醒!这是result[i]
带给你的错觉!
这就是闭包,匿名函数function() {return i};
仅仅代表返回i
,那i
是多少哪?
当匿名函数执行的时候,从作用域链中寻找,匿名函数的寻i
历险记如下:
嗯,我自己的作用域里没定义i
,接着往上走,诶!老爹createFunctions
的作用域里定义了i
,它的值又是多少?这个for循环
(十年前就执行完了)里说了i
是10
!
好,返回10
。函数运行结束。
现在说说第二个createFunctions。首先
=function(num){
return function(){
return num;
};
}(i);
这玩意叫立即执行函数表达式,字面意思,运行到这它立刻就执行了!
i=0时,它立刻就return了一个
function(){
return num;
};
同第一个分析的一样,我们看看这个num
是多少
自己作用域里没num
,往上走,诶!老爹(同样没名字)的作用域里有num
,作为形参被赋值了0,找到了!
跟祖父createFunctions
里i
现在是多少有关系吗?毫无关联!
闭包问题还真是常见呢,大概讲下原因吧,题主用到的第二个例子中,我们通过闭包机制将 i
赋值给了 num
,继而将值保存在了内存中,因此会依次输出我们想要的结果。
详细机制请题主可参考:
- 《细说 Javascript 函数篇(三) : 闭包和引用》
- 《Javascript - 深入闭包机制》
你这什么书这个恶心啊,循环给数组一个函数,还不去执行,里面的i当然带不进去了,不用return那么多函数,只需要让result[i] 等于后面函数自执行不就行了吗?
function createFunctions(){
var result =new Array();
for(var i=0;i<10;i++){
result[i]=(function(){
return i;
})();
}
return result;
}
楼主你试试这是不是你想要的东西。
js里任何一个函数都是闭包,别把这个问题想复杂了
这么看来你这本书上代码想实现的结果更简单,是这个:
function createFunctions(){
var result =new Array();
for(var i=0;i<10;i++){
result[i] = i
}
return result;
}
这作者简直没事找事
闭包的值是取的时候的值。你外层函数返回时,里边那些函数没有执行,根本没有访问 i
。等你调用它时,它们去访问 i
,它们看到,哦,i
等于 10。