Node.js V8 什么时候分配和编译闭包?

When are closures allocated and compiled in Node.js V8?

根据我目前对 VM 及其行为的假设,我认为每次命中闭包的定义时都会分配和编译闭包;与在闭包外声明的函数相比,闭包只分配和编译一次(因为它们被放置在某个地方,它们的定义只被命中一次)。这个假设是否正确?

所以如果我在 socket.on('data', function (data) {...}) 中有一个闭包,V8 会分配新内存(并可能重新编译)闭包 每次 套接字接收到数据?

Based on my current assumptions about VM's and their behavior, I figure closures are allocated and compiled every time their definition is hit;

in contrast to functions declared outside closures which are allocated and compiled once.

false,每次命中它们的定义时也会编译这些,但它们通常放在一个只命中一次定义的地方。
闭包被设计为多次定义并且每次包含不同的 variables/values.
这就是我们区分这是 simple/anonymous 函数还是闭包

的方式

V8 allocates new memory every time data is received by the socket

不,这个匿名函数编译一次,然后传递给事件处理程序。事件处理程序现在引用了此函数,并在每次收到数据时调用它。

添加事件侦听器时,此示例中的定义也只命中一次。

I figure closures are allocated and compiled every time their definition is hit

不是真的。闭包编译一次,但每次它们的定义被命中时都会分配。最重要的是,你必须区分分配和编译。

  • 每个函数的代码(即在源代码中的相同位置)只编译一次,即使该函数在不同环境中被实例化多次。
    在每个实例化上进行编译是没有意义的,就像为每个调用进行编译一样毫无意义(尽管,这实际上是 "interpreter" 所做的,并且边界是流动的,例如对于不在第一次通话的时间)。
    如果代码成为优化候选者,或者如果优化失败并且必须取消优化,则代码可能会再次编译(使用更慢但更复杂的编译器);但这不是重点。

  • 每个函数在命中其定义时都是allocated/instantiated,这与局部函数(嵌套在其他函数中)特别相关。
    然而,非闭包函数的分配成本为零,因为不需要存储环境指针,也不需要实例对象。

So if I have a closure in socket.on('data', function (data) {...}), V8 allocates new memory (and possibly re-compiles) the closure every time data is received by the socket?

不是 function (data) {…},它仅实例化一次并传递给 on 调用。

但是,是的,如果您有一个在 部分实例化的闭包,那么每次接收数据和调用处理程序时都会分配一些内存。不过这个不用担心,内存分配便宜又快。

如果您正在寻找技术细节,我建议阅读 http://mrale.ph/blog/2012/09/23/grokking-v8-closures-for-fun.html(即使它已经有几年历史了)。