2011-07-14 20 views
30

En algún momento del pasado, leí algo que me dio la idea de que las funciones anónimas en JavaScript pueden consumir una sorprendente cantidad de memoria (porque llevan todo el alcance actual con ellas), mientras que el nombre (¿estático?) las funciones no tienen este problema.¿Hay algún inconveniente en el uso de funciones anónimas en JavaScript? P.ej. ¿uso de memoria?

No recuerdo dónde lo leí, así que no puedo volver atrás, volver a leerlo y resolverlo por mi cuenta.

Tengo dos preguntas:

  1. ¿Existen situaciones en las funciones anónimas pueden utilizar suficiente memoria para que sea digno de preocupación? (De ser así, ¿tiene un ejemplo?)
  2. ¿Existen otros inconvenientes en las funciones anónimas (a diferencia de las funciones nombradas/estáticas)?
+0

Excelente pregunta. He agotado mis votos por el día. ¿Alguien más puede hacer +1 por mí? –

+0

@Michael ya lo hizo. Gran pregunta –

+0

Ha habido una pregunta similar en SO sobre la * implementación * de cierres, pero todavía tengo que ver una con una respuesta satisfactoria. Es decir, ¿los motores de JavaScript * modernos * son lo suficientemente inteligentes para mantenerse alrededor de los objetos en el [[alcance]] a los que * se puede acceder *? Obviamente, esta optimización no es práctica para aplicar en presencia de 'eval', etc ... –

Respuesta

7

Todas las funciones de JavaScript se comportarán de la misma manera, ya que heredan los entornos de variables en toda la cadena de alcance que los lleva hasta ellos mismos. Esto es igualmente cierto para las funciones anónimas y nombradas.

Esta cadena de referencias a los entornos externos permanece con cada función, incluso si la función se pasa a un alcance completamente diferente.

Tradicionalmente, esto significa que todas las variables en una cadena dada tienen una referencia retenida mientras el cierre interno continúe existiendo. Aunque en los navegadores modernos que compilan el código, es probable que exista un análisis de las variables a las que realmente se hace referencia, y solo se retendrán, lo que permite que otras que ya no se mencionan sean basura.

Sin embargo, hay otras situaciones en las que una función anónima es un desperdicio.

Aquí hay un poco común de código:

for(var i = 0; i < 100; i++) { 
    (function(j) { 
     setTimeout(function() { console.log(j); }, 1000); 
    })(i); 
} 

Ésta es una situación en la que una función anónima es un poco más derrochador de una función llamada porque estás recreando una función idéntica 100 veces durante el bucle cuando se podría simplemente reutilizar uno nombrado.

function setConsole(j) { 
    setTimeout(function() { console.log(j); }, 1000); 
} 

for(var i = 0; i < 100; i++) { 
    setConsole(i); 
} 

Esto tiene exactamente la misma cabeza de cierre, pero es más eficiente, ya que sólo has construido una función para crear cada nueva variable de entorno.

http://jsperf.com/immediate-vs-named(Gracias a @Felix Kling para el jsPerf.)

Por lo tanto, con respecto al cierre en particular, sí, hay gastos generales siempre y cuando mantenga el cierre mediante alguna referencia permanente. Diría que es bueno evitar esto si es posible pero no ser obsesivo al respecto. A veces, un nuevo entorno variable agregado a la cadena de alcance es simplemente la mejor solución.


EDIT:Here's an article from Google. Específicamente, vea Evitando peligros con cierres. para obtener información sobre el impacto en el rendimiento de la extensión de la cadena de alcance y para un reclamo de que las funciones anónimas son "más lentas" que las funciones nombradas.

+1

** Nota del moderador ** _Los comentarios en esta respuesta se eliminaron porque degeneraron en más ruido que la señal. Por favor, mantenga los comentarios constructivos, profesionales y sobre todo en el tema. –

+1

Gracias a @Tim Post para la eliminación. El resultado de la discusión relevante con OP, así como la prueba de rendimiento proporcionada por @Felix Kling se han agregado a la respuesta. – user113716

3

Creo que lo que probablemente leyó fue sobre el problema de fuga de memoria de cierre de IE.

Mire this article al respecto.

Básicamente, en versiones anteriores de IE, el recolector de basura no podía manejar referencias circulares que involucraban objetos DOM. Dado que los cierres son muy propicios para tales referencias circulares, podrían conducir fácilmente a pérdidas de memoria molestas en IE.

+0

Sí, no estoy seguro de que fue eso - Recuerdo las referencias circulares de IE , y que tenía que ver con los cierres (nunca pude obtener todos los detalles para que se quedaran en mi cabeza), pero creo que * lo que leí era un punto más general sobre las funciones anónimas. –

0

Esto es cierto, debido a los cierres que se crean. como regla general, el mayor problema con la práctica son las preocupaciones de rendimiento con IE (especialmente las versiones anteriores de IE), que tiene un historial terrible de tratar con estos adecuadamente.

Cuestiones relacionadas