gpt4 book ai didi

c# - 是否需要引用变量才能将它们包含在闭包中?

转载 作者:行者123 更新时间:2023-11-30 18:48:21 43 4
gpt4 key购买 nike

在创建闭包时(使用Javascript或C#),在创建闭包时范围内的所有变量是否都“封闭”在其中?还是只是新创建的方法中引用的变量?

示例C#代码:

private void Main() {
var referenced = 1;
var notReferenced = 2; // Will this be enclosed?
new int[1].Select(x => referenced);
}

示例JavaScript代码:
    var referenced = 1;
var notReferenced = 2; // Will this be enclosed?
var func = function () {
alert(referenced);
}

(通过使用Java闭包创建循环引用来阅读IE中的内存泄漏时,我遇到了问题。 http://jibbering.com/faq/notes/closures/#clMem)
注意:“封闭”一词是指MSDN称为“捕获”。 ( http://msdn.microsoft.com/en-us/library/bb397687.aspx)

最佳答案

您在这里有两个问题。将来,当您有两个问题时,您可以考虑发布两个单独的问题。

When creating a closure in Javascript, are all variables in the scope at the time of the closure's creation "enclosed" in it?



您没有说明要谈论的是“JavaScript”的许多版本。我假设您正在谈论ECMAScript 3语言的正确实现。如果您正在谈论其他版本的“JavaScript”,请说出您正在谈论哪个版本。

ECMAScript 5更新了有关词汇环境和“评估”工作方式的规则。自2001年以来,我一直未成为39技术委员会的成员,并且我一直未与ECMAScript 5规范的最新更改保持同步。如果您想在最近的ECMAScript 5规则中找到答案,请寻找该规范的专家;我不是

在ECMAScript 3中,您的问题的答案是肯定的。在这一点上,ECMAScript 3规范非常清晰,但是您无需查看规范即可知道确实如此:
function f()
{
var referenced = 1;
var notReferenced = 2;
var func = function ()
{
alert(referenced);
alert(eval("notReferenced"));
}
return func;
}
f()();

如果未捕获“notReferenced”,“eval”如何正常工作?

所有这些都在ECMAScript规范中进行了说明,但是我可以在这里简单地总结一下。

每个变量都与一个“变量对象”相关联,“变量对象”具有其属性为变量名称的属性。函数f的变量对象与f的激活对象相同,即,每次调用f时都会神奇创建的对象。变量对象具有三个属性:“已引用”,“未引用”和“功能”。

有一个称为“全局对象”的变量对象,它表示任何函数外部的代码。它具有属性“f”。

每个执行上下文都有一个作用域链,该作用域链是尝试评估标识符时将搜索其属性的对象列表。

每个功能对象都有一个与其关联的作用域链,该作用域链是创建该功能时生效的作用域链的副本。

与“f”关联的作用域链是全局对象。

当执行进入“f”时,执行上下文的当前作用域链将激活对象“f”压入到该对象。

当“f”创建分配给“func”的功能对象时,其关联的作用域链是执行上下文当前作用域链的副本,即包含“f”的激活的作用域链以及全局目的。

好,现在所有对象都已正确设置。 f返回func,然后将其调用。这将为该功能创建一个激活对象。从函数对象中获取执行上下文的作用域链-请记住,它是“f”的激活对象加上全局对象-然后将当前的激活对象压入作用域链的该副本。由于我们现在正在执行的匿名函数既没有参数也没有本地变量,因此本质上是无操作的。

然后,我们尝试评估“警报”;我们查找范围链。当前激活和“f”激活没有任何称为“alert”的内容,因此我们询问全局对象,并说是的,alert是一个函数。然后,我们评估“引用”。它不在当前激活对象上,但在f的激活对象上,因此我们获取其值并将其传递给警报。

下一行相同。全局对象告诉我们,有方法“警报”和“评估”。但是“eval”当然很特殊。 Eval获取当前作用域链以及字符串参数的副本。 Eval将字符串解析为程序,然后使用当前作用域链执行该程序。该程序查找“notReferenced”并找到它,因为它在当前作用域链上。

如果您对此 Realm 还有其他疑问,建议您阅读ECMAScript 3规范的第10和13章,直到您完全理解它们为止。

让我们更深入地研究您的问题:

When creating a closure in Javascript, are all variables in the scope at the time of the closure's creation "enclosed" in it?



要明确回答该问题,您需要精确地告诉我们“闭包”的含义-ECMAScript 3规范没有定义该术语。 “闭包”是指功能对象还是功能对象捕获的作用域链?

请记住,所有这些对象都是可变的-作用域链本身不是可变的,但是链中的每个对象都是可变的!实际上,在创建作用域链或函数对象时,是否在创建时就存在 变量变量实际上是无关紧要的。变量来了,变量去了。

例如,可以捕获在函数对象创建时尚未创建的 变量!
function f()
{
var func = function ()
{
alert(newlyCreated);
}
eval("var newlyCreated = 123;");
return func;
}
f()();

显然,“newlyCreated”在创建功能对象时不是变量,因为它是在功能对象之后创建的。但是,当调用函数对象时,它位于f的激活/变量对象上。

同样,可以在执行功能对象时删除创建嵌套功能对象时存在的变量。

关于c# - 是否需要引用变量才能将它们包含在闭包中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6774013/

43 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com