¿Cómo se representan los cierres y ámbitos en tiempo de ejecución en JavaScript

Esta es principalmente una pregunta por curiosidad. Considere las siguientes funciones

var closure ;
function f0() {
    var x = new BigObject() ;
    var y = 0 ;
    closure = function(){ return 7; } ;
}
function f1() {
    var x = BigObject() ;
    closure =  (function(y) { return function(){return y++;} ; })(0) ;
}
function f2() {
    var x = BigObject() ;
    var y = 0 ;
    closure = function(){ return y++ ; } ;
}

En todos los casos, después de que se haya ejecutado la función, creo que no hay forma de llegar ax y entonces el BigObject se puede recolectar basura, siempre quex es la última referencia a ella. Un intérprete de mente simple capturaría toda la cadena de alcance cada vez que se evalúa una expresión de función. (Por un lado, debe hacer esto para hacer llamadas a eval trabajo - ejemplo a continuación). Una implementación más inteligente podría evitar esto en f0 y f1. Una implementación aún más inteligente permitiríay para ser retenido, pero nox, como se necesita para que f2 sea eficiente.

Mi pregunta es ¿cómo manejan los motores JavaScript modernos (JaegerMonkey, V8, etc.) estas situaciones?

inalmente, aquí hay un ejemplo que muestra que las variables pueden necesitar ser retenidas incluso si nunca se mencionan en la función anidada.

var f = (function(x, y){ return function(str) { return eval(str) ; } } )(4, 5) ;
f("1+2") ; // 3
f("x+y") ; // 9
f("x=6") ;
f("x+y") ; // 11

Sin embargo, existen restricciones que impiden que uno se cuela en una llamada para evaluar de una manera que el compilador podría pasar por alto.

Respuestas a la pregunta(2)

Su respuesta a la pregunta