闭包将它们的执行上下文保留到什么级别?

Till what level do closures keep their execution contexts?

来自方法的函数 return 保留其 parent 执行上下文 的副本,这称为闭包。但是,如果函数在另一个函数内部,而另一个函数又在另一个函数内部,就像这样:

const a = function() {
    const aa = 'aa';
    return function() {
        const bb = 'bb';
        return function() {
            return aa;
        }
    }
}

现在,如果我这样称呼它:

a()()();

它将 return "aa" 因为 nexted-most 方法似乎可以访问其 grandparent 上下文。那么,当这些内部方法被 returned 时,所有内部方法是否都保留它们嵌套的所有祖先的执行上下文?

闭包只是对定义函数的环境的引用。

在代码示例中(为了方便解释,我给每个函数都起了个名字):

const a = function() {
    const aa = 'aa';
    return function b() {
        const bb = 'bb';
        return function c() {
            return aa;
        }
    }
}

函数c 将引用函数b 的局部作用域。同样,函数 b 将引用函数 a.

的局部范围

这条引用链就是所谓的范围链,Javascript 将遍历这条链,直到找到标识符 aa

对定义函数的环境的引用保存在 Ecmascript 规范调用函数对象的 [[Environment]] 槽的内部槽中。

So, do all inner methods keep the execution contexts of all their ancestors in which they're nested, when these inner methods are returned?

对于几乎所有实际用途:是。

虽然 JS 引擎确实进行了优化,但实际上只保留需要保留的数据,而不是整个词法环境。

例如,给定:

const a = () => {
    const foo = 1;
    const bar = 2;
    const b = () => {
        console.log(foo);
        debugger;
    }
}

a()();

大多数 JS 引擎将使 foo 可用于 b 但是,因为 b 不使用 bar,它们将丢弃 bar 并且它调试器将无法使用。