下面是一些代码,类似于让我悲伤的代码:
for(var i=0;i<3;i++){
var Proof = true
if (i == 0){
Proof = false
//var CallBack = function(){alert(Proof);}; // true????
var CallBack = function(){alert(i);};
}
}
// Whatever happened to local scope? shouldn't CallBack be undefined now?
CallBack()// alert(3), should be 0?
CallBack没有未定义,它提醒真实或3,有人可以向我解释发生了什么事情使它像这样做?我缺少一些本地关键字,还是JS没有范围?我没有使用任何框架,并希望得到一些帮助,如何解决这个问题,并正确地做这件事...
答案 0 :(得分:2)
JavaScript根本没有块范围(但是,见下文)。所有变量都在它们出现的函数中声明(或者在整个全局范围内,如果它们在全局范围内)。
假设您引用的代码是其范围内唯一的代码,则完全与此相同:
var i;
var Proof;
var Callback;
for(i=0;i<3;i++){
Proof = true
if (i == 0){
Proof = false
//CallBack = function(){alert(Proof);}; // true????
CallBack = function(){alert(i);};
}
}
// Whatever happened to local scope? shouldn't CallBack be undefined now?
CallBack()// alert(3), should be 0?
更多(在我的博客上):Poor, misunderstood var
CallBack()// alert(3), should be 0?
不,3
是正确的,因为这是i
被称为时CallBack
的值。 CallBack
是对创建它的上下文的闭包。它对上下文(包括i
变量)有持久引用,而不是创建它时存在的副本。
如果您想获得0
,则必须CallBack
关闭除i
以外的其他内容,这些内容不会发生变化。执行此操作的典型方法是使用将值传递到的构建器函数:
function buildCallBack(index) {
return function() { alert(index); };
}
然后:
CallBack = buildCallBack(i);
i
的值作为参数buildCallBack
传递到index
。 buildCallBack
创建一个函数,该函数关闭对buildCallBack
的调用的上下文并使用该index
参数。由于该参数的值永远不会更改,因此回调会警告0
(在本例中)而不是3
。
更多(在我的博客上):Closures are not complicated
我上面说“尚未”的原因是规范的下一个版本(ES6)将为新的let
和const
关键字以及块函数声明引入新的block-scope semantics。 var
将保持不变,但如果使用let
来声明变量,则它具有块范围而不是函数/全局范围。
答案 1 :(得分:1)
当调用CallBack时,for
循环已经完成。所以i
等于3。
如果您希望i
是本地的,您应该这样写:
var CallBack;
for(var i=0;i<3;i++){
(function(index) {
var Proof = true
if (index == 0){
Proof = false
//var CallBack = function(){alert(Proof);}; // true????
CallBack = function(){alert(index);};
}
})(i);
}
CallBack()
这是demo
<强>更新强>
这是另一种选择:
var CallBack;
for(var i=0;i<3;i++){
var Proof = true
if (i == 0){
Proof = false
CallBack = (function(index) {
return function(){alert(index);};
})(i);
}
}
CallBack()
更新2
阐释:
通过编写(function(index) {...})(i)
我们声明一个匿名函数并立即调用它(我们也可以编写function(index) {...}(i)
但我认为第一种情况更清楚)。在javascript中,function
也是一种设置另一个变量范围的方法,因此在我们的例子中,我们“记住”i
变量中index
变量的当前状态,该变量仅在我们的变量中可见匿名函数。
当调用'CallBack'时,alert
显示0
,因为i
在调用该函数时等于0
。