微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

JavaScript闭包如何处理变量?

假设我们有一个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忍者的秘密”一书,每个闭包都有自己的私有变量集(包括稍后定义的变量,如someOuterVariable):

所以在containerFunction外部引用的innerFunction1和innerFunction2作为innerFunction1link和innerFunction2link将具有其“私有气泡”,其中包含完整的变量集.在“A点”,两个函数都将执行正常并将输出

I'm 1 42 1
I'm 2 42 2

然后,当我将someOuterVariable设置为“WAT?!”时,输出为:

I'm 1 WAT?! 3
I'm 2 WAT?! 4

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

更新:

即使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

解决方法

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

必须清楚的是它是参考而不是副本.

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

作为补充说明:每次调用函数时都会创建JavaScript范围(还有其他范围,最明显的是全局范围,但也可以使用with或try / catch创建).

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐