这是一段代码示例,类似于让我感到悲伤的代码:
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 不是未定义的,它会发出 true 或 3 的警报,有人可以向我解释一下是什么原因导致它像这样吗?是否缺少一些本地关键字,或者 JS 没有作用域?我没有使用任何框架,希望能得到一些帮助来解决这个问题,并正确地做这种事情......
最佳答案
JavaScript 根本没有 block 范围(但是,请参见下文)。所有变量都在它们出现的整个函数中声明(或者在整个全局范围内,如果它们在全局范围内)。
假设您引用的代码是其范围内的唯一代码,它完全与此相同:
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
是正确的,因为这是调用 CallBack
时 i
的值。 CallBack
是对创建它的上下文的闭包。它有一个对上下文(包括 i
变量)的持久引用,而不是创建它时存在的内容的副本。
如果你想得到 0
,你必须让 CallBack
关闭 i
以外的东西,一些不会不改变。这样做的典型方法是使用将值传递给的构建器函数:
function buildCallBack(index) {
return function() { alert(index); };
}
然后:
CallBack = buildCallBack(i);
i
的值作为参数 index
传递给 buildCallBack
。 buildCallBack
创建一个函数,关闭调用 buildCallBack
的上下文并使用该 index
参数。由于该参数的值永远不会改变,回调提醒 0
(在本例中)而不是 3
。
更多(在我的博客上):Closures are not complicated
我上面说“还”的原因是下一版本的规范 (ES6) 将引入新的 block-scope semantics对于新的 let
和 const
关键字和 block 函数声明。 var
将保持不变,但如果您使用 let
来声明一个变量,它具有 block 作用域而不是函数/全局作用域。
关于javascript - Javascript 的 Scope 如何工作,出现意外行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20990661/