javascript - Javascript 的 Scope 如何工作,出现意外行为?

标签 javascript scope

这是一段代码示例,类似于让我感到悲伤的代码:

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 传递给 buildCallBackbuildCallBack 创建一个函数,关闭调用 buildCallBack 的上下文并使用该 index 参数。由于该参数的值永远不会改变,回调提醒 0(在本例中)而不是 3

更多(在我的博客上):Closures are not complicated


我上面说“还”的原因是下一版本的规范 (ES6) 将引入新的 block-scope semantics对于新的 letconst 关键字和 block 函数声明。 var 将保持不变,但如果您使用 let 来声明一个变量,它具有 block 作用域而不是函数/全局作用域。

关于javascript - Javascript 的 Scope 如何工作,出现意外行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20990661/

相关文章:

javascript - 如何检查 AngularJS 模板 HTML 中的数字

javascript - 如果字符串有多个点,则仅从最后一个点开始拆分

javascript - 无效值错误: myMap is not a function

c++ - 为什么 C++ 参数作用域会影响命名空间内的函数查找?

c# - for 循环中计数器变量的范围是什么?

c++ - 如何使大量现有功能在类的范围内可用?

javascript - 用于清除/删除过滤器的 Google Sheets 脚本

javascript - 在 OL3 中强制渲染 ImageCanvas 层?

Javascript 和 JQuery "this"范围错误

Laravel 5 全局范围 : injecting variable