Hi,

> My tactic is going to be to stop defining them inline, therefore not
> causing a closure...

Yeah, I mean, it's not something you need to be paranoid about at all,
just something to keep in the back of your mind when you're dealing
with large numbers of things.  Small numbers of things are not a
problem, and of course use-and-forget closures (such as those
typically used with Enumerable.each) are not a problem because you
don't keep them.  And there are (lots of) times when a closure is
exactly what you want.  But something to keep in mind as part of the
larger picture of your code.

I should have mentioned that if you have this situation and the
closure is necessary (as they frequently are), you can minimize the
memory used by clearing any references that you no longer need.  So
with my doNiftyThing function earlier (again, a flawed example, but
there we are), if the closure is necessary and you're worried about
keeping the other things referenced, you could add this line at the
end:

    stuff = target = log = p = undefined;

The variables 'stuff', 'target', 'log', and 'p' are all still
referenced by the closure, but at least the things the *variables*
used to reference (the target element, the log element, the new
paragraph element, the 'stuff') are no longer referenced by those
variables, and so are eligible for cleanup if nothing else references
them.

-- T.J. :-)


On Nov 14, 10:28 am, bluezehn <[EMAIL PROTECTED]> wrote:
> Thanks T.J., very useful.
> I'm defining a lot of closures for my event handlers, ie, defining the
> functions for them inline (element.observe('click', function() { bla
> bla bla });), which are probably therefore using far too much memory.
> My tactic is going to be to stop defining them inline, therefore not
> causing a closure, and making sure that before I remove an element
> from the dom I'm no longer observing it.
>
> On Nov 14, 7:59 am, "T.J. Crowder" <[EMAIL PROTECTED]> wrote:
>
> > Hi,
>
> > > 1 ) But the problem is it's turned out to be a bit of a memory eater
> > > as there's quite a lot of methods on both classes.
>
> > That shouldn't be a problem if you're using Class.create, it assigns
> > the methods to the prototypes so the methods are shared across all
> > instances.  Are you trying to create private variables and then public
> > methods with access to them by creating methods within initialize?
> > E.g., are you doing this:http://pastie.org/314662
>
> > That kind of thing is sometimes recommended as a means of having true
> > private variables in JavaScript classes, and then having public
> > members that can access those private variables.  The problem with it
> > is that each *instance* of the class gets its own copy of the methods,
> > as well as the variables -- they're not shared on the prototype.  So
> > if you have 100 instances, each with 10 methods, you have 1,000
> > methods in memory.  (Which shouldn't be a problem if they're small,
> > but it could have been 10!)
>
> > > 2) If you remove an element from the DOM, are observers for that
> > > element also removed?
>
> > No, you'll want to call $('element').stopObserving() first -- with no
> > event name or handler, stopObserving unhooks all of the event handlers
> > for the element that were hooked up with observe()[1].  If you think
> > any of the element's children also have event handlers, you'll need to
> > unhook them as well.  Usually your application logic should give you
> > the information you need to do that in a targeted way, but if you need
> > to do it not knowing which children are hooked up, you can do
> > something like this:
>
> > function massUnhookAndRemove(element) {
> >     element = $(element);
> >     if (element) {
> >         // Unhook all children's handlers
> >         element.select('*').invoke('stopObserving');
>
> >         // Unhook element's handlers
> >         element.stopObserving();
>
> >         // Remove element
> >         element.remove();
> >     }
>
> > }
> > > 3) Does
> > > var bla = $('foo');
> > > // do some stuff with bla, leave it lying around on an object
>
> > Not if bla eventually goes out of scope so it's eligible for
> > reclamation.  But if you define any closures in that same scope, bla
> > will be kept alive becaues the closures have a reference to it.  E.g.:
>
> > function doNiftyThing(stuff) {
> >     var log;
> >     var p;
> >     var target;
>
> >     // Do it, and hook it up
> >     target = $('target');
> >     target.update(stuff);
> >     target.observe('click', function(evt) {
> >         // ...
> >     });
>
> >     // Log it
> >     log = $('log');
> >     p = new Element('p');
> >     p.update('Showed stuff');
> >     log.appendChild(p);
>
> > }
>
> > It may not look like it, but the closure being used as an event
> > handler on 'target' has live references to 'log' and 'p' (and
> > 'target', and 'stuff'), so the memory they point to will stay in use
> > as long as that closure exists.  Stupid example I supposed because of
> > course that logging stuff would be its own function, but you get the
> > idea.  Even if the closure doesn't seem to use something, it has
> > references to everything in scope where it's defined.  I've done an
> > article on closures that might help.[2]
>
> > > Constitute a memory leak? Or is that only when you also do:
> > > var bla = $('foo');
> > > $('foo').obj = bla;
>
> > JavaScript doesn't have a problem with circular references; the GC
> > will handle that gracefully (if nothing else references either object,
> > it'll clean them both up).  Internet Explorer has issues with circular
> > references involving non-JavaScript native objects, like DOM nodes --
> > it won't clean them up.  See Crockford's article on that.[3]
>
> > [1]http://prototypejs.org/api/event/stopObserving
> > [2]http://blog.niftysnippets.org/2008/02/closures-are-not-complicated.html
> > [3]http://javascript.crockford.com/memory/leak.html
>
> > HTH,
> > --
> > T.J. Crowder
> > tj / crowder software / com
>
> > On Nov 13, 11:22 pm, bluezehn <[EMAIL PROTECTED]> wrote:
>
> > > I've extensively used class.create for a calendar - each week has a
> > > class containing 7 days, also represented as objects of a class.
>
> > > 1 ) But the problem is it's turned out to be a bit of a memory eater
> > > as there's quite a lot of methods on both classes. Should architecture
> > > like this be a problem with memory?
>
> > > Regardless of the answer to the above question (which I really, really
> > > hope is no!), I'd also like to know the answer to some more
> > > questions...
>
> > > 2) If you remove an element from the DOM, are observers for that
> > > element also removed?
>
> > > 3) Does
> > > var bla = $('foo');
> > > // do some stuff with bla, leave it lying around on an object
>
> > > Constitute a memory leak? Or is that only when you also do:
> > > var bla = $('foo');
> > > $('foo').obj = bla;
>
> > > 4) What are other causes of common memory leaks in prototype usage?
>
> > > Thanks alot for any answers.
>
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Prototype & script.aculo.us" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/prototype-scriptaculous?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to