我正在研究一个学校作业,比较
Swift和
JavaScript中的高阶函数/闭包实现.
Apple documentation明确提到了Swift中的全局和嵌套函数作为闭包的特例,但我无法在JavaScript中找到任何类似/冲突的信息.
粗略搜索返回this blog post,这表明JS中的全局范围是作为一个闭包实现的,但我似乎找不到可靠的证据,包括在我的报告中. (大多数搜索只返回JS闭包/范围的概述,这对我没用.)
如果任何JS专家都熟悉这个实现,我真的很感激这些信息.
干杯!
最佳答案 词汇范围
词典将词汇定义为“与语言的词汇或词汇有关”. 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.
因此对于上面的例子,首先继承global的variableEnvironment,然后继承first的variableEnvironment.
这种遗产如何运作?
在执行期间,每当调用新函数时,都会创建一个新的执行上下文,因此会创建一个新的variableEnvironment.这个新的variableEnvironment有一个名为outerLex的属性,它保存创建它的词法范围的variableEnvironment.
那么我们的例子中函数second的变量环境如何?
{
c: ... // own variables
outerLex: {
b: .. // variables of outer lexical scope
outerLex: {
a: .. // global variable
}
}
}
它开始有意义了吗?这也应解释为什么变量在不同范围内以相同名称出现时会被“遮蔽”.
还要注意,变量按词法接近度排列优先级.
我已经解释了闭包.你在别处读到的所有理论都应该开始有意义.
最里面的variableEnvironment有一个outerLex属性,它引用它上面的variableEnvironment,从而防止外部作用域的变量被垃圾收集.垃圾收集通过检查如何以及哪些元素引用哪些元素来工作. Read more here
即使函数首先返回并结束执行,函数second仍然可以有效地引用其中定义的变量b,因为它具有对其variableEnvironment的引用.
让我们深入挖掘(并回答你的问题)
创建函数时,将自动继承variableEnvironment.
我们已经在上面看到,variableEnvironment的继承创建了一个函数闭包.
因此,在函数创建时形成一个闭包,如果函数已经返回,它就无所事事(常见的神话)
此外,JavaScript对象通过引用工作.
因此,外部变量被引用,而不是复制到variableEnvironment中
回答你的问题
每个函数都在JavaScript中创建一个闭包.
一个常见的误解是只有内部函数才会产生闭包,而事实并非如此.
全局范围中的函数也形成闭包,但它们的闭包很无聊,因为它只引用全局变量环境,它在任何情况下都是可见的.
最后,您说您需要一个文档来链接您的作业. This should suffice 😉
[编辑]:我讨厌术语.每当outerLex属性为空时,有些人都喜欢说没有形成闭包.咩.
[编辑2]:本文中的大部分内容与网络上的内容相反.请阅读ECMA-262标准以支持您的任何索赔.