根据我目前对虚拟机及其行为的假设,我估计每次命中闭包定义时都会分配并编译闭包。与在闭包外部声明的函数相反,这些函数只被分配和编译一次(因为它们被放置在其定义的某个位置,因此仅被命中一次)。这个假设正确吗?
因此,如果我在中有一个闭包socket.on('data', function (data) {...})
,则每次套接字接收到数据时,V8都会分配新的内存(并可能重新编译)该闭包?
我估计每次命中闭包时都会分配和编译闭包
并不真地。闭包只编译一次,但是每次命中它们的定义时都会分配。最重要的是,您必须区分分配和编译。
每个函数的代码(即在源代码中的相同位置)仅被编译一次,即使该函数在不同的环境中被多次实例化也是如此。
对每个实例进行编译都是毫无意义的,就像为每个调用进行编译毫无意义一样(尽管这实际上是“解释器”所做的,并且边界是可变的,例如对于懒散的编译,它不会在每次编译之前就发生)。第一次致电)。
如果代码成为优化的候选者,或者优化失败并且必须取消优化,则可能会再次编译代码(使用速度较慢但功能更复杂的编译器)。但这不是重点。
每个函数在定义时都会被分配/实例化,这与本地函数(嵌套在其他函数中)特别相关。
非封闭函数的分配成本为零,因为不需要存储环境指针,因此不需要实例对象。
因此,如果我在中有一个闭包
socket.on('data', function (data) {...})
,则每次套接字接收到数据时,V8都会分配新的内存(并可能重新编译)该闭包?
不是function (data) {…}
,它仅实例化一次并传递给on
调用。
但是,是的,如果您在…
部分中实例化了一个闭包,那么每次接收到数据并调用处理程序时,该闭包都会分配一些内存。但是不必担心,内存分配既便宜又快速。
如果您正在寻找技术细节,我建议您阅读http://mrale.ph/blog/2012/09/23/grokking-v8-closures-for-fun.html(即使已经使用了几年)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句