30

¿Alguien puede explicar en detalle cómo los motores de Javascript manejan las referencias circulares? ¿Hay una gran diferencia entre los navegadores o incluso node.js?Referencias circulares en Javascript/Recolector de basura

De lo que estoy hablando es de una referencia atrás/siguiente explícita dentro de los objetos. Por ejemplo:

var objA = { 
    prop: "foo", 
    next: null 
}; 

var objB = { 
    prop: "foo", 
    prev: null 
}; 

objA.next = objB; 
objB.prev = objA; 

Ahí vamos. Si hacemos un console.log(objA), podemos ver que creamos una cadena infinita. La gran pregunta es, ¿es esto malo? ¿Crea fugas de memoria cuando no se limpian explícitamente?

Así que lo que tenemos que

objA.next = null; 
objB.prev = null; 

o serán los recolectores de basura cuidar de nosotros en constelaciones como esto?

Respuesta

53

Cualquier recolector de basura medio decente manejará los ciclos.

Los ciclos son solo un problema si se hace un recuento de referencias ingenuo.

La mayoría de los recolectores de basura no hacen recuento de ref (tanto porque no puede manejar los ciclos, y porque es ineficiente). En su lugar, simplemente siguen cada referencia que pueden encontrar, comenzando desde "raíces" (típicamente variables globales y basadas en la pila), y marcan todo lo que pueden encontrar como "alcanzable".

Luego, simplemente reclaman el resto de la memoria.

Los ciclos no son un problema porque solo significa que se alcanzará el mismo nodo varias veces. Después de la primera vez, el nodo ya estará marcado como "alcanzable", por lo que el GC sabrá que ya ha estado allí y se saltará el nodo.

Aún más primitivos Los GC basados ​​en recuento de referencias implementan típicamente algoritmos para detectar y romper ciclos.

En resumen, no es algo de lo que deba preocuparse. Me parece recordar que Javascript GC de IE6 no pudo manejar los ciclos (podría estar equivocado, ha pasado un tiempo desde que lo leí, y ha pasado mucho, mucho más tiempo desde que toqué IE6), pero en cualquier implementación moderna, es No hay problema.

El punto entero en un recolector de basura es abstraer la gestión de memoria. Si tiene que hacer esto usted mismo, su GC está roto.

Consulte MDN para obtener más información sobre la recolección de basura moderna y los algoritmos de marcaje y barrido que se utilizan.

+1

¿Qué pasa con http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml?showone=Closures#Closures ¿está mal? – Sandro

+2

@Sandro leyó mi respuesta nuevamente. :) Un GC sano maneja ciclos muy bien. Todo lo que es más nuevo que IE6 se puede considerar cuerdo. Si necesita soportar IE6, debe preocuparse por el manejo incorrecto de los ciclos. Aparentemente, la guía de Google está escrita bajo la suposición de que esos navegadores rotos deben ser compatibles, por lo que deben saltar algunos aros adicionales. – jalf

+0

@Sandro Hay algo especial en ese ejemplo: un elemento DOM es una parte de la referencia circular. En general, se perdería la memoria hasta que cierre la página. Si recuerdo correctamente, sin embargo, IE no siempre elimina las referencias al DOM cuando navegas. (Al parecer, ¿eso rompió algunas páginas?) –

Cuestiones relacionadas