在 JavaScript 的上下文中说“将闭包分配给变量”是不是正确?
Posted
技术标签:
【中文标题】在 JavaScript 的上下文中说“将闭包分配给变量”是不是正确?【英文标题】:Is saying to "assign a closure to a variable" correct in the context of JavaScript?在 JavaScript 的上下文中说“将闭包分配给变量”是否正确? 【发布时间】:2021-02-02 08:47:03 【问题描述】:我很好奇示例代码中第 20 行的解释。
在第 9 行声明了名为
func1
的变量。 已分配给 函数foo()
调用返回的闭包。`
我知道函数foo()
的调用会返回函数bar
和指向其词法范围内的变量a
的指针。既然闭包是a function combined with all of the variables in its lexical scope, including function and class names
,我可以说我是把变量func1
赋给闭包了吗?
这个解释是否使用了正确的词而不是含糊不清?你能提出一个更好更简洁的解释和解释第 20 行吗?
function foo()
let a = 1;
return function bar()
a += 100;
console.log(a);
let func1 = foo();
let func2 = foo();
func1(); // ???
func2(); // ???
func1(); // ???
func2(); // ???
/*
On line 9 variable with name `func1` is declared.
!! It's assigned to the closure that is returned by the function `foo()` invocation.
The closure contains a pointer to the variable `a` that is in the lexical scope of the function `bar` that is returned by the `foo` invocation.
On line 10 variable with name `func2` is declared. It's assigned to the value of closure that is returned by the function `bar()` invocation. The closure contains a pointer to the variable `a` that is in the lexical scope of the function `bar`.
Variables accessible through the closure during the `func1` invocation and `func2` invocation are two separate independent variables that just happen to have the same name (`a`).
That is, this program would print the following to the console:
- 101
- 101
- 201
- 201
*/
【问题讨论】:
func1 在哪里?我个人说变量是“封闭的”,正如 Crockford 先生所说的那样。 我会避免说“分配了一个闭包”。这有点误导,太技术化了。 1. 赋值通常是设置变量的值,例如x = 1
是将1
赋值给x
。你倒着说(意译)x
被分配给1
。 2.“闭包”其实没什么特别的。 JS 中的每个函数都是一个闭包。我只想说foo()
是一个高阶函数,结果是一个函数。
【参考方案1】:
我知道函数 foo() 的调用会返回 函数 bar 和指向变量 a 的指针
闭包不是这样工作的。调用foo()
只返回函数bar
,它不返回指向变量a
的指针。
每个环境都链接到它的外部环境,当javascript在当前环境中找不到变量时,它会跟随链接到外部环境。不同环境之间的这种联系使闭包成为可能。
当函数foo
被定义时,javascript将指向全局环境的链接保存在一个槽中,该槽中规范调用函数的[[Environment]]
槽。
当函数 foo
被调用时,会为该调用创建一个新环境,并将其链接到保存在函数 foo
上的 [[Environment]]
槽中的环境(让我们将此环境称为 EnvFoo
.)
类似地,当定义bar
函数时,javascript 将在调用函数foo
时创建的环境链接(EnvFoo
) 保存在[[Environment]]
插槽中bar
函数上。当调用bar
时,会创建一个新环境(让我们将此环境称为EnvBar
),它会获得保存在bar
函数(EnvFoo
)上[[Environment]]
槽中的环境的链接,作为其外部环境。
所以当你调用bar
函数时,变量a
在当前环境中不存在(EnvBar
),所以javascript在当前环境的外部环境中寻找变量a
,即@ 987654349@。这个环境包含变量a
,所以它从这个外部环境中获取a
的值,即EnvFoo
。
这就是闭包的工作原理,即每个环境都保持对其外部环境的引用,当 javascript 在当前环境中找不到变量时,它会跟随指向当前环境的外部环境的链接并在那里查找变量。它继续跟随外部环境的链接,直到它到达全球环境。
下图将让您了解每个环境在您的案例中是如何关联的。
P.S:我上面解释的都是我从@T.J Crowder'sbook学到的东西。如果你想了解更多细节,我建议你参考这本书,因为它在书中有详细的解释。
【讨论】:
:-) 感谢您的支持!【参考方案2】:我知道函数
foo()
的调用会返回函数bar
和指向其词法范围内的变量a
的指针。
它只返回一件事:foo
创建的函数 bar
。函数bar
本身具有对创建它的环境的引用,因此是对a
变量的引用;它关闭那个环境。所以bar
是一个闭包。您在 JavaScript 代码中创建的所有函数都是闭包。
...我可以说我将变量 func1 分配给闭包吗?
你不能给闭包分配任何东西;相反。您可以分配给变量(各种),您可以初始化常量。你在const func1 = foo();
中所做的是用foo
返回的函数(如果你愿意,你可以说“闭包”)初始化常量func1
。
【讨论】:
TJ,所以,下面的解释会更好:在线[x]变量func1
被初始化并分配给foo()
调用返回的函数,其中包括指向变量@987654334的指针@.
@DmytroNayda - 更接近,但没有“到”。变量func1
被分配了foo()
返回的函数。或者将foo()
返回的函数分配给到 func1
。 (然后,是的,该函数在概念上具有一个引用——我不会说“指针”——指向创建它的上下文,其中包含用于调用 foo
的 a
变量。)跨度>
@PeterSeliger - 谢谢,我写了foo
,我的意思是bar
! :-)(请注意,它返回的是计算命名函数表达式的结果,而不是表达式本身。)以上是关于在 JavaScript 的上下文中说“将闭包分配给变量”是不是正确?的主要内容,如果未能解决你的问题,请参考以下文章