En réponse aux doutes de @Beetroot-Beetroot (que j'ai aussi, il faut l'avouer), j'ai creusé un peu plus. J'ai mis en place ce violon et a utilisé le Chronologie des outils de développement du chrome et cet article comme une ligne directrice. Dans le fiddle, deux handlers presque identiques créent une fermeture avec 2 objets date. Le premier ne fait référence qu'à a
le second fait référence aux deux a
et b
. Bien que dans les deux cas, seuls a
ne peuvent jamais être réellement exposées (valeurs codées en dur), la première fermeture utilise beaucoup moins de mémoire. Je ne peux pas dire avec certitude si cela est dû à JIC (compilation juste à temps) ou à la magie de l'optimisation JS de V8. Mais d'après ce que j'ai lu, je dirais que c'est la GC de V8 qui désalloue b
lorsque le tst
retourne, ce qui n'est pas le cas dans le second cas ( bar
références b
quand tst2
retours). J'ai l'impression que ce n'est pas si farfelu, et je ne serais pas du tout surpris de découvrir que FF et même IE fonctionneraient de la même manière.
J'ai juste ajouté cette mise à jour, qui n'est peut-être pas pertinente, par souci d'exhaustivité et parce que j'ai l'impression qu'un lien vers la documentation de Google sur les outils de développement est une bonne idée. valeur ajoutée en quelque sorte.
Cela dépend en quelque sorte, mais en règle générale, tant que vous ne pouvez pas faire référence à l'option classInstance
plus, elle devrait être GC'ed, indépendamment de ses propres références circulaires. J'ai testé un grand nombre de constructions similaires à celle que vous décrivez ici. Peut-être que cela vaut la peine de jeter un coup d'œil
J'ai constaté que les fermetures et les fuites de mémoire ne sont pas si courantes ou faciles à éviter (du moins, plus maintenant).
Mais comme le dit la réponse acceptée : il est pratiquement impossible de savoir quand un code va fuir.
En relisant votre question, je dirais : non, vous ne ferez pas fuir la mémoire : l'option classInstance
n'a pas été créée dans la portée globale, mais elle est transmise à diverses fonctions (et donc à diverses portées). Ces scopes se désintègrent chaque fois que la fonction revient. classInstance
ne sera pas GC'ed s'il a été passé à une autre fonction/scope. Mais dès que la dernière fonction qui fait référence à classInstance
retourne, l'objet est marqué pour la GC. Bien sûr, il peut s'agir d'une référence circulaire, mais c'est une référence à laquelle on ne peut accéder que depuis sa propre portée.
On ne peut pas vraiment appeler cela une fermeture, non plus : les fermetures se produisent quand il y a une forme de exposition à la portée externe, ce qui n'est pas le cas dans votre exemple.
Je ne suis pas doué pour expliquer ce genre de choses, mais récapitulons :
var foo = (function()
{
var a, b, c, d;
return function()
{
return a;
}
})();
Le GC va désallouer la mémoire b
, c
et d
référence : ils sont sortis du champ d'application, il n'y a aucun moyen d'y accéder...
var foo = (function()
{
var a, b, c, d;
return function()
{
a.getB = function()
{
return b;
}
a.getSelf = function()
{
return a;//or return this;
}
return a;
}
})();
//some code
foo = new Date();//
Dans ce cas, b
n'aura pas non plus de GC, pour des raisons évidentes. foo
expose a
et b
, donde a
est un objet qui contient une référence circulaire. Bien que dès que foo = new Date()
, foo
perd toute référence à a
. Bien sûr, a
se réfère toujours à lui-même, mais a
n'est plus exposé Il peut faire référence à ce qu'il veut. La plupart des navigateurs s'en moquent et GC a
et b
. En fait, j'ai vérifié et Chrome, FF, et IE8 tous les GC le code ci-dessus parfaitement ... pas de soucis, alors.