JavaScript中的全局/嵌套函数是作为闭包实现的吗?

时间:2016-03-02 03:10:18

标签: javascript

我正在完成一项学校作业,比较Swift和JavaScript中的高阶函数/闭包实现。

http://www.nltk.org/api/nltk.html#nltk.text.TextCollection在Swift中明确提到全局和嵌套函数作为闭包的特例,但我无法在JavaScript中找到任何类似/冲突的信息。

粗略搜索返回Apple documentation,这表明JS中的全局范围是作为闭包实现的,但我似乎无法找到可靠的证据,包括在我的报告中。 (大多数搜索只是返回JS闭包/范围的概述,这对我来说并不有用。)

如果任何JS大师都熟悉这个实现,我真的很感激这些信息。

干杯!

1 个答案:

答案 0 :(得分:2)

Lexical Scoping

字典将词汇定义为“与语言的词汇或词汇有关”。 JavaScript中函数的词法范围由代码中函数的物理位置静态定义。

var a = "Top of all";

function first(){
 var b = "I am first";
  function second(){
   var c = "I am second";
   }
}

这形成了一个词汇层次结构:

全球 - >第一 - >第二

variableEnvironment Read 10.4 and 10.5

JavaScript中的每个可能的范围都有自己的执行上下文。每个执行上下文都有自己的variableEnvironment - 这是该上下文的所有变量都存在的地方。函数的每次调用都会建立并输入一个新的执行上下文,从而建立一个新的variableEnvironment。

Take Away:每个variableEnvironment也将继承其直接词法范围的variableEnvironment

我也可以用这种方式构建它:每个variableEnvironment都会继承创建它的上下文的variableEnvironment

因此,对于上面的示例,first继承了global的variableEnvironment,second继承了first的variableEnvironment。

这种继承如何运作?

在执行期间,每当调用新函数时,都会创建一个新的执行上下文,因此会创建一个新的variableEnvironment。这个新的variableEnvironment有一个名为outerLex的属性,它保存了创建它的词法范围的variableEnvironment。

那么我们示例中函数second的variableEnvironment如何看起来像?

{
 c: ... // own variables
 outerLex: {
   b: .. // variables of outer lexical scope
   outerLex: {
      a: .. // global variable
   }

 }
}

它开始有意义了吗?这也应解释为什么变量在不同范围内以相同名称出现时会被“遮蔽”。

另请注意,变量按词汇接近度优先

我已经解释了闭包。你在别处读到的所有理论都应该开始有意义。

最里面的variableEnvironment有一个outerLex属性,引用它上面的variableEnvironment,从而防止外部作用域的变量被垃圾回收。垃圾收集通过检查如何以及哪些元素引用哪些元素来工作。 Read more here

即使函数first已经返回并结束执行,函数second仍然可以有效地引用其中定义的变量b,因为它具有对其variableEnvironment的引用。

让我们深入挖掘(并回答你的问题)

创建函数时,会自动继承variableEnvironment。 我们已经在上面看到,variableEnvironment的继承创建了一个函数闭包。

所以,在函数创建时会形成一个闭包,如果函数已经返回则没有任何关系(常见的神话)

此外,JavaScript对象通过引用工作。

因此,在变量环境中引用外部变量,而不是复制

回答你的问题

每个函数都在JavaScript中创建一个闭包。 这是一个常见的误解,只有内部函数才会产生闭包,而事实并非如此。

全局范围内的函数也形成闭包,但它们的闭包很无聊,因为它只引用全局变量环境,它在任何情况下都是可见的。

最后,您说您需要一个文档来链接您的作业。 This should suffice ;)

[编辑]:我讨厌术语。每当outerLex属性为空时,有些人就会说没有形成闭包。 MEH。

[编辑2]:本文中的大部分内容与网络上的内容相反。请阅读ECMA-262标准,以支持任何您的声明。