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创建).

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...