我在哪里可以找到有关实现闭包的详细信息(如在JavaScript或Scheme中)?

时间:2011-02-28 16:45:56

标签: javascript compiler-construction closures

我对编译器理论以及传统的过程语言和面向对象语言(如C,Pascal和Java)的运行时环境非常熟悉。我希望详细了解如何实现JavaScript之类的语言的运行时结构,特别是与闭包相关:如何管理存储,何时分配闭包,如何决定何时释放闭包存储。如果没有挖掘V8或Rhino的源代码,你能指出我可以提供这种描述的论文或书籍或教程吗?

感谢。

3 个答案:

答案 0 :(得分:1)

它相当简单,它是嵌套命名空间的一个克隆,所以它与编译器理论相反,它是运行时分配的命名空间,用于解析符号查找,与编译语言相比,它将符号编译成静态偏移。

但基本上所有这意味着符号查找针对名称空间的链接列表发生,从本地名称空间开始,到封闭的名称空间(闭包)。

在javascript中,命名空间只是一个对象,其引用计数为任何打开的函数,并引用该命名空间

e.g。

var links = //a list of links identified set somehwere else
for(var i = 0, l = 3; l--; i++){
   (function(n){
      links[i].onclick = function(){ alert(n); }
   })(i)
}

在上面的代码中,links [i]用于访问数组,但是在点击链接时,我将增加,从而与链接的数量不同。所以n是在父命名空间中设置的,所以当它触发时,alert(n)将是准确的。

global
|
|\
| +-- function(n=0) <- link0.onclick = function()
|\
| +-- function(n=1) <- link1.onclick = function()
 \
  +-- function(n=2) <- link2.onclick = function()

这分为3个堆栈帧,每次迭代i一个。并且hte'onclick ='表达式右侧的函数有一个对堆栈帧的引用,因为它是词法父类,它启动它的符号查找。

他们最终都会看到相同的命名空间,因为他们共享祖父母。

一些链接:

https://developer.mozilla.org/en/a_re-introduction_to_javascript

这个最小的方案比v8源更容易阅读:

http://code.google.com/p/chibi-scheme/

答案 1 :(得分:1)

这种技术称为lambda lifting,它完全是静态的(因此,没有昂贵的运行时命名空间查找)。

答案 2 :(得分:1)

This article解释了javascript中闭包的实现。