existe el siguiente codigo
function fn1 () { const a = 1; const b = 2; const c = 3; function fn2() { console.log("xx"); } function fn3() { console.log(a); console.log(c); } return fn2; } const clo = fn1(); console.dir(clo);Cuando ejecuté este código en Chrome Console, obtuve esto:
Sé que fn3 hace referencia a la variable de fn1, pero solo devuelvo fn2, ¿por qué hay un cierre en fn2 [[Scopes]] ?
¡Espero que las personas que conocen esta razón le den algún consejo! gracias.
Tanto fn2 como fn3 se crean dentro de fn1 , por lo que ambos cierran (tienen una referencia a) el objeto de entorno léxico creado para la llamada a fn1 . (El objeto de entorno léxico es lo que contiene los enlaces para a , b , c y algunas otras cosas). Eso es cierto ya sea que usen ese enlace (como lo hace fn3 , accediendo a las variables locales de fn1 ) o no ( fn2 ).
Algunos motores de JavaScript han experimentado con optimizar eso cuando sea posible: eliminando el enlace de una función al entorno donde se creó (enlazándolo directamente al entorno exterior en su lugar). IIRC, V8 (en Chrome) experimentó con hacer eso, pero descubrió que en la mayoría de los casos el costo de tiempo de ejecución de hacer ese análisis era más costoso que simplemente dejar que el cierre permaneciera, por lo que no llevó adelante ese trabajo cuando reemplazaron las partes internas. del motor hace unos años.
Por separado, algunos motores han experimentado con la optimización del contenido de los cierres, eliminando los enlaces del objeto de entorno léxico que no utiliza ninguna de las funciones que lo cierran. De su captura de pantalla, parece que V8 todavía hace esa parte, al menos en casos triviales como ese, ya que solo se enumeran los enlaces que usa fn3 ( a y c , no b ). En un nivel de especificación, todos esos enlaces se conservarían (no es que podamos decirlo en nuestro código), pero los motores son libres de optimizar donde la optimización no conduce a un comportamiento fuera de especificación.
Cuando devuelve fn2 , se crea un cierre que hace que todas las variables disponibles en el ámbito externo estén disponibles.
JS no verifica si realmente usa esas variables, sin embargo, se agregan al cierre.