闭包将它们的执行上下文保留到什么级别?
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
并且它调试器将无法使用。
来自方法的函数 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
并且它调试器将无法使用。