JavaScript闭包如何处理变量?

时间:2013-07-02 15:35:25

标签: javascript closures

假设我们有一个containerFunction,其中定义了两个函数:

var innerFunction1link;
var innerFunction2link;

function containerFunction() {
    var someInnerVariable = 1;

    innerFunction1link = innerFunction1;
    innerFunction2link = innerFunction2;

    function innerFunction1() {
        console.log("I'm 1 " + someOuterVariable + " " + (someInnerVariable++));
    }

    function innerFunction2() {
        console.log("I'm 2 " + someOuterVariable + " " + (someInnerVariable++));
    }
}


containerFunction();
var someOuterVariable = 42;

// Point A
innerFunction1link();
innerFunction2link();

someOuterVariable = "WAT?!";

// Point B
innerFunction1link();
innerFunction2link();

现在的问题。根据“JavaScript Ninja的秘密”一书,每个闭包都有自己的私有变量集(包括稍后定义的变量,如someOuterVariable):

private bubbles

innerFunction1innerFunction2之外引用containerFunctioninnerFunction1link作为innerFunction2linkI'm 1 42 1 I'm 2 42 2 将会有“私人气泡​​”,其中包含完整的变量集。在“A点”,两个函数都将执行正常并输出:

someOuterVariable

然后,当我将"WAT?!"设置为I'm 1 WAT?! 3 I'm 2 WAT?! 4 时,输出为:

someOuterVariable

如何在两个“私人气泡​​”中实际更新someInnerValuesomeOuterVariable的价值(如果有1000个这样的气泡怎么办?)?它是否实际跟踪所有变量的所有引用?如果一个闭包更新innerFunction,它的值将如何填充到其他闭包?

更新

即使function containerFunction1() { var someInnerVariable = 1; innerFunction1link = innerFunction1; function innerFunction1() { console.log("I'm 1 " + someOuterVariable + " " + (someInnerVariable++)); } } function containerFunction2() { var someInnerVariable = 1; innerFunction2link = innerFunction2; function innerFunction2() { console.log("I'm 2 " + someOuterVariable + " " + (someInnerVariable++)); } } containerFunction1(); containerFunction2(); var someOuterVariable = 42; innerFunction1link(); innerFunction2link(); someOuterVariable = "WAT?!"; innerFunction1link(); innerFunction2link(); 将在不同的上下文中定义,它们仍将“共享”变量:

I'm 1 42 1 
I'm 2 42 1
I'm 1 WAT?! 2
I'm 2 WAT?! 2 

输出:

{{1}}

2 个答案:

答案 0 :(得分:6)

比使用私有气泡更好的描述是每个函数都保留对其定义范围的引用。

必须清楚它是引用而不是副本

这解释了两个innerFunction都指向相同的范围,因此指向同一组变量。这些变量也可以在外部作用域中或通过指向此作用域的任何函数进行更改。

作为补充说明:每次调用函数时都会创建JavaScript范围(还有其他范围,最值得注意的是全局范围,但也可以使用with或{{1}创建的范围})。

答案 1 :(得分:1)

  

innerFunction1innerFunction2之外引用containerFunctioninnerFunction1link作为innerFunction2linkcontainerFunction将会有“私人气泡​​”,其中包含完整的变量集。

不是真的。它们的气泡很空,但是从它们内部你可以透过气泡的墙壁看到containerFunction更大的气泡。在那里,您可以看到4个变量:someInnerVariableinnerFunction1innerFunction2innerFunction1link。从这个泡沫中,您可以看到全球泡沫,包括innerFunction2linksomeVariablecontainerFunctionsomeOuterVariable和{{1}}变量。

因此,不是在气泡中复制大量的每个变量,它们只是指向更高气泡中共享变量的指针。如果它们从任何地方更新,您也可以从私人泡泡中看到它。

现在用“范围”替换“bubble”一词的每个出现: - )