1

I am finding myself rather confused regarding javascript garbage collection and how to best encourage it.

What I would like to know is related to a particular pattern. I am not interested in whether the pattern itself is considered a good or bad idea, I am simply interested in how a browsers garbage collector would respond, i.e would the references be freed and collected or would it cause leaks.

Imagine this pattern:

   TEST = {     
                init : function(){                        
                      this.cache = {
                           element : $('#element')
                      };
                },
                func1 : function(){
                       this.cache.element.show();                     
                },
                func2 : function(){                                            
                       TEST.cache.element.show(); 
                },
                func3 : function(){
                       var self = this;                      
                       self.cache.element.show(); 
                },
                func4 : function(){
                       var element = this.cache.element;
                       element.show();
                }
                func5 : function(){
                        this.auxfunc(this.cache.element);
                }
                auxfunc1 : function(el){
                         el.show();
                }
                func6 : function(){
                       var el = getElement();
                       el.show();
                }
                getElement : function(){
                       return this.cache.element;
                }
    }

Now imagine that on page load TEST.init() is called;

Then later at various times the various functions are called.

What I would like to know is if caching elements or objects or anything else upon initialization and referring to them throughout the lifetime of an application, in the manner shown above, effects a browsers garbage collector positively or negatively.

Is there any difference? Which method best encourages garbage collection? Do they cause leaks? Are there any circular references? if so where?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
gordyr
  • 6,078
  • 14
  • 65
  • 123
  • 1
    You can refer to an object as long as you want, provided it's still in use. You should clear your references to DOM objects if they have been removed from the DOM though. – Paul Grime Apr 25 '13 at 14:15
  • @PaulGrime Thanks Paul, i think I understand this. But what concerns me is if each time i call this.cache.element, is it creating a new reference within that functions scope ON TOP of the original cache reference which will not be garbage collected? – gordyr Apr 25 '13 at 14:17

1 Answers1

5

This code, in itself, shouldn't cause any memory leaks. Especially not in modern browsers. It's just an object, like you have tons of others in any script. It all depends on where, how, and how long you reference it.

The basic rule is that, whenever an object is no longer referenced anywhere in the code (directly/by variable or indirectly/ through closure accessing a scope), the GC will flag and swipe.
If you use the above code, and then assign something else to TEST the object literal it referenced could be GC'ed, if no other variable references the original object.

Of course, predicting memory leaks in JS is an inexact science. In my experience, they're not nearly as common as some would have you believe. Firebug, Chrome's console (profiler) and IE debugger get you along a long way.

Some time ago I did some more digging into this matter resulting in this question. Perhaps some links, and findings are helpful to you...

If not here's a couple of tips to avoid the obvious leaks:

  • Don't use global variables (they don't actually leak memory permanently, but do so, for as long as your script runs).
  • Don't attach event handlers to the global object (window.onload ==> leaks mem in IE <9 because the global object is never fully unloaded, hence the event handler isn't GC'ed)
  • Just wrap your script in a huge IIFE, and use strict mode whenever possible. That way, you create a scope that can be GC'ed in its entirety on unload.
  • Test, test and test again. Don't believe every blogpost you read on the subject! If something was an issue last year, that needn't be the case today. This answer might not be 100% accurate anymore by the time you read this, or because just this morning some miracle-patch for JS GC'ing was written by erm... Paris Hilton or some other alien life-form.

Oh, and to answer your in-comment question: "But what concerns me is if each time i call this.cache.element, is it creating a new reference within that functions scope ON TOP of the original cache reference which will not be garbage collected?"
The answer is no. Because this will reference the TEST object, and the init function assigns the object a property cahche, that in itself is another object literal with 1 property referencing a jQ object. That property (cache) and all that is accessible through it will sit in memory right until you either delete TEST.cache or delete TEST. if you were to create var cahce = {...}; that object would be GC'ed when the ini function returns, because a variable cannot outlive its scope, except for when you're using closures and exposing certain variables indirectly.

Community
  • 1
  • 1
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • Thanks, as simple as it sounds thats exactly what I needed to know and thus will be awarding you the answer. – gordyr Apr 25 '13 at 14:23
  • @gordyr: You're welcome... I added some more info on mem-leaks because I still find that there is too much conflicting information on the subject out there. Some say circular references are the only cause, others say that doesn't apply today. One post states that IE9 still leaks when referencing DOM-nodes in a closure, others say that was fixed in IE8... Hence, the link to that older question of mine. It's a lengthy text, but there is some information in there, too :D. Anyways happy coding – Elias Van Ootegem Apr 25 '13 at 14:29
  • Fantastic... This has been extremely helpful. I cannot thank you enough :) – gordyr Apr 25 '13 at 14:30
  • Your final edit was like a lightbulb going off in my head. You sir, are a godsend. cheers! – gordyr Apr 25 '13 at 14:45
  • @gordyr: hold on to that, and keep at it. Once you start to grasp the way JS scopes/references/closures and the `this` keyword work, you'll soon find out what it is that makes JS such an expressive language – Elias Van Ootegem Apr 25 '13 at 14:53