confusión sobre la recolección de basura entre los cierres

No he estado seguro acerca de las reglas de la recolección de basura JS en torno a un cierre por un tiempo, así que creo que también podría preguntar ... Aquí hay un buen ejemplo que tengo curiosidad sobre la participación de jQuery $.each método:

storeSelection: function() {
    var enabledIds = {};

    $.each(this.nodes, function(index, node) {
        if (node.enabled) {
            enabledIds[ node.id ] = true;
        }
    });

    this.selection = enabledIds;
}

El fragmento anterior es, por supuesto, parte de un objeto literal. Entonces, creé un nuevo objeto en la parte superior de la función externa que almacenará las ID de los elementos habilitados dentro de una matriz. Usando jQuery .each() método, estoy recorriendo la matriz de elementos y registrando ID habilitados. Finalmente, guardo la selección como miembro del objeto principal.

Mi pregunta involucra esa función interna que hace referencia a la enabledIds objeto del alcance externo. Ya que enabledIds se quedará, ¿eso impide que se recopile la función interna? Supongo que no, porque es solo una variable que se borra al final de la función interna, ¿verdad? Para convertirse en una fuga, asumo que la función interna necesitaría hacer una referencia directa al objeto externo, como en:

$.each(this.nodes, function(index, node) {
    this.badIdea = enabledIds;
    if (node.enabled) {
        enabledIds[ node.id ] = true;
    }
});

Sin embargo... Siempre estoy confuso con esta regla. ¡Cualquier ayuda para aclarar esta confusión sería apreciada!

preguntado el 22 de mayo de 12 a las 17:05

2 Respuestas

No, incluso su segundo ejemplo no sería suficiente para causar una fuga. badIdea se adjunta a los nodos individuales, y el $.each el bloque saldría y se recolectaría como basura. Todos los navegadores modernos utilizan un algoritmo de "marcar y barrer" para la recolección de elementos no utilizados de javascript, que sigue las asociaciones padre a hijo y recopila cualquier "inalcanzable", es decir, cualquier cosa a la que no se pueda acceder mediante uno de estos árboles.

contestado el 22 de mayo de 12 a las 18:05

Tienes razón, las variables de la función interna (index, node) se recolectarán como basura, porque ya no se puede acceder a ellos.

En este ejemplo, ¿puede acceder bigstr?

a = function() {
        var bigstr = new Array(1000000).join('x');
        return function() { return bigstr; };
    }();

Sí tu puedes: a(), por lo que no se recopila. ¿Qué pasa con este ejemplo:

a = function() {
        var bigstr = new Array(1000000).join('x');
        return function(n) { return eval(n); };
    }();

De nuevo, puedes: a('bigstr').

Pero que tal este:

a = function() {
        var smallstr = 'x';
        var bigstr = new Array(1000000).join('x');
        return function(n) { return smallstr; };
    }();

Ya no puede acceder a él y es un candidato para la recolección de elementos no utilizados.

contestado el 22 de mayo de 12 a las 18:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.