javascript - 执行上下文和闭包

标签 javascript closures

我知道如何实现闭包,但我很难理解为什么会发生闭包。例如:

function foo(){
    var a = 4;
    return function innerFoo(){
        alert(a);
    };
};
var bar = foo();
bar();                   // alerts 4

当我看到上面的代码时,我知道会发生什么,但是当我试图从逻辑上遵循它时,它就没有意义了。我认为我对执行上下文及其范围链的理解是错误的。

这是我希望程序运行的方式:

function foo(){
    var a = 4;
    return function innerFoo(){
        alert(a);
    };
};

var bar = foo(); // function foo() is executed, creating a foo execution context(EC)
                 // fooEC = {scopeChain: [fooEV.VO, globalEC.VO],
                 //                  VO: {innerFoo: pointer to innerFoo(),
                 //                              a: 4}};

                 // So, the pointer to innerFoo() is returned to bar
                 // fooEC is exited
bar(); // bar points to code in innerFoo(), creates a innerFoo execution context
       // innerFooEC = {scopeChain: [innerFoo.VO, globalEC.VO],
       //                       VO: { }};

       // interpreter searches innerFooEC.VO for variable "a", none found, looks
       // down the scope chain at the global variable object,
       // globalEC = {scopeChain: [globalEC.VO],
       //                     VO: {foo: pointer to foo(),
       //                          bar: pointer to innerFoo()}};  
       // a is undefined

我哪里出错了?

最佳答案

错误在

bar points to code in innerFoo()

闭包不仅仅是指向代码的指针,它还是指向代码加上环境的指针;这是定义 a 的环境。

当你执行一个闭包时,范围链是定义闭包时(即在foo内)处于事件状态的范围链,而不是进行调用的范围链.

请注意,闭包捕获变量,而不是。这可以通过以下方式观察到:

function getset(x) {
    var a = x;
    function getter() { return a; }
    function setter(x) { a = x; }
    return [getter, setter];
}

var gs1 = getset(12);
var gs2 = getset(34);

console.log(gs1[0]()); // --> 12
console.log(gs2[0]()); // --> 34
gs1[1](1122);
gs2[1](3344);
console.log(gs1[0]()); // --> 1122
console.log(gs2[0]()); // --> 3344

即每对 getter/setter 将在两个闭包之间共享自己的变量,但与另一对分开。

根据我的经验,这是在循环中创建闭包时最常犯的错误的来源:

for (var i=0; i<10; i++) {
    var node = document.createElement("div");
    node.textContent = "click me (" + i + ")";
    node.onclick = function() { alert(i); };
    document.body.appendChild(node);
}

在这段代码中,所有 10 个元素在单击时都会显示相同的数字 (10),因为所有闭包都共享相同的 i 变量循环,10 是变量的最终值。

关于javascript - 执行上下文和闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28119922/

相关文章:

javascript - 使用 jQuery 在 div 上设置背景颜色?

快速将 Any 转换为闭包

arrays - SWIFT OS X - 闭包语句内的多个语句,调试工具?

javascript - 将对象推送到状态对象中的数组。 ReactJS

javascript - JS - 如何使用 `this`在不同范围内引用同一个对象?

javascript - Bootstrap Modal 在不被查看或关闭的情况下立即消失

Javascript/正则表达式 : Lookbehind Assertion is causing a "Invalid group" error

javascript - jQuery 从字符串中删除特殊字符等

javascript - 在 Meteor 中如何找到 DOM 元素(渲染后)?

rust - 如何借用一个展开的 Option<T>?