¿Qué es la recolección de basura de JavaScript? ¿Qué es importante que un programador web comprenda sobre la recolección de basura de JavaScript para poder escribir un código mejor?
297
¿Qué es la recolección de basura de JavaScript? ¿Qué es importante que un programador web comprenda sobre la recolección de basura de JavaScript para poder escribir un código mejor?
Respuestas:
Eric Lippert escribió una publicación de blog detallada sobre este tema hace un tiempo (comparándolo adicionalmente con VBScript ). Más exactamente, escribió sobre JScript , que es la propia implementación de ECMAScript de Microsoft, aunque muy similar a JavaScript. Me imagino que puede asumir que la gran mayoría del comportamiento sería el mismo para el motor de JavaScript de Internet Explorer. Por supuesto, la implementación variará de un navegador a otro, aunque sospecho que podría tomar una serie de principios comunes y aplicarlos a otros navegadores.
Citado de esa página:
El objetivo principal de la recolección de basura es permitir que el programador no se preocupe por la administración de la memoria de los objetos que crea y usa, aunque, por supuesto, a veces no hay que evitarlo; siempre es beneficioso tener al menos una idea aproximada de cómo funciona la recolección de basura .
Nota histórica: una revisión anterior de la respuesta tenía una referencia incorrecta al
delete
operador. En JavaScript, eldelete
operador elimina una propiedad de un objeto y es completamente diferente adelete
C / C ++.fuente
delete
incorrectamente; por ejemplo, en el primer ejemplo, en lugar dedelete foo
, primero debe eliminar el detector de eventos mediantewindow.removeEventListener()
y luego usarfoo = null
para sobrescribir la variable; en IE,delete window.foo
(pero nodelete foo
) también habría funcionado sifoo
fuera global, pero incluso así no funcionaría en FF u Operadelete
es un operador unario (una expresión), no una declaración (es decir:)delete 0, delete 0, delete 3
. Parece una declaración cuando se expresa mediante una declaración de expresión.Tenga cuidado con las referencias circulares cuando los objetos DOM están involucrados:
Patrones de pérdida de memoria en JavaScript
Tenga en cuenta que la memoria solo se puede recuperar cuando no hay referencias activas al objeto. Este es un error común con los cierres y los controladores de eventos, ya que algunos motores JS no verificarán qué variables se referencian realmente en las funciones internas y solo mantendrán todas las variables locales de las funciones de cierre.
Aquí hay un ejemplo simple:
Una ingenua implementación de JS no se puede recopilar
bigString
mientras el controlador de eventos esté disponible. Hay varias formas de resolver este problema, por ejemplo, configurarbigString = null
al final deinit()
(delete
no funcionará para variables locales y argumentos de función:delete
elimina las propiedades de los objetos, y el objeto variable es inaccesible - ES5 en modo estricto incluso arrojará unReferenceError
si lo intentas para eliminar una variable local!).Recomiendo evitar los cierres innecesarios tanto como sea posible si le importa el consumo de memoria.
fuente
Buena cita tomada de un blog
El componente DOM es "recolección de basura", al igual que el componente JScript, lo que significa que si crea un objeto dentro de cualquiera de los componentes y luego pierde el rastro de ese objeto, eventualmente se limpiará.
Por ejemplo:
Cuando llama a esa función, el componente JScript crea un objeto (llamado bigArray) al que se puede acceder dentro de la función. Sin embargo, tan pronto como la función regrese, "perderá el rastro" de bigArray porque ya no hay forma de referirse a ella. Bueno, el componente JScript se da cuenta de que has perdido el rastro y, por lo tanto, bigArray se limpia y recupera su memoria. El mismo tipo de cosas funciona en el componente DOM. Si dice
document.createElement('div')
algo similar, entonces el componente DOM crea un objeto para usted. Una vez que pierda el rastro de ese objeto de alguna manera, el componente DOM limpiará lo relacionado.fuente
Que yo sepa, los objetos de JavaScript son basura recolectada periódicamente cuando no quedan referencias al objeto. Es algo que sucede automáticamente, pero si desea ver más acerca de cómo funciona, a nivel C ++, tiene sentido echar un vistazo al código fuente de WebKit o V8
Por lo general, no necesita pensarlo, sin embargo, en los navegadores más antiguos, como IE 5.5 y versiones anteriores de IE 6, y tal vez las versiones actuales, los cierres crearían referencias circulares que, cuando no se controlan, terminarían consumiendo memoria. En el caso particular al que me refiero sobre cierres, fue cuando agregaste una referencia de JavaScript a un objeto dom, y un objeto a un objeto DOM que se refirió al objeto JavaScript. Básicamente, nunca se pudo recopilar y, con el tiempo, el sistema operativo se volvería inestable en las aplicaciones de prueba que se creaban bloqueos. En la práctica, estas filtraciones suelen ser pequeñas, pero para mantener limpio el código, debe eliminar la referencia de JavaScript al objeto DOM.
Por lo general, es una buena idea usar la palabra clave delete para desreferenciar de inmediato objetos grandes como datos JSON que ha recibido y ha hecho lo que sea necesario, especialmente en el desarrollo web móvil. Esto hace que el próximo barrido del GC elimine ese objeto y libere su memoria.
fuente
mark-and-sweep
algoritmos de estilo más nuevos se encargan de esto .La recolección de basura (GC) es una forma de administración automática de memoria al eliminar los objetos que ya no se necesitan.
cualquier proceso de proceso con memoria sigue estos pasos:
1 - asigna el espacio de memoria que necesitas
2 - haz algo de procesamiento
3 - libera este espacio de memoria
Hay dos algoritmos principales utilizados para detectar qué objetos ya no son necesarios.
Recolección de basura de conteo de referencias : este algoritmo reduce la definición de "un objeto ya no es necesario" a "un objeto no tiene ningún otro objeto que haga referencia a él", el objeto se eliminará si no tiene ningún punto de referencia
Algoritmo de marca y barrido : conecta cada objeto a la fuente raíz. cualquier objeto no se conecta a la raíz u otro objeto. Este objeto será eliminado.
Actualmente, los navegadores más modernos utilizan el segundo algoritmo.
fuente
Todos los motores de JavaScript tienen sus propios recolectores de basura, y pueden diferir. La mayoría de las veces no tiene que lidiar con ellos porque simplemente hacen lo que se supone que deben hacer.
Escribir un mejor código depende principalmente de qué tan bueno conoces los principios de programación, el lenguaje y la implementación particular.
fuente
mira esto
En Javascript no te importa la asignación de memoria y la desasignación. Todo el problema se exige al intérprete de Javascript. Las fugas aún son posibles en Javascript, pero son errores del intérprete. Si está interesado en este tema, puede leer más en www.memorymanagement.org
fuente
En Windows, puede usar Drip.exe para encontrar pérdidas de memoria o verificar si su rutina de memoria libre funciona.
Es realmente simple, solo ingrese la URL de un sitio web y verá el consumo de memoria del procesador integrado de IE. Luego presione actualizar, si la memoria aumenta, encontró una pérdida de memoria en algún lugar de la página web. Pero esto también es muy útil para ver si las rutinas para liberar memoria funcionan para IE.
fuente
Los tipos de referencia no almacenan el objeto directamente en la variable a la que está asignado, por lo que la variable de objeto en este ejemplo en realidad no contiene la instancia del objeto. En cambio, contiene un puntero (o referencia) a la ubicación en la memoria donde existe el objeto
si asigna una variable a otra, cada variable obtiene una copia del puntero, y ambas aún hacen referencia al mismo objeto en la memoria.
de Los principios de JavaScript orientado a objetos - NICHOLAS C. ZAKAS
fuente