Yep cheers T.J. This all makes alot of sense. Nice to understand
everything rather than just go about doing things in a certain way
because it's the "done" thing!

On Nov 14, 11:02 am, "T.J. Crowder" <[EMAIL PROTECTED]> wrote:
> 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 prototype-scriptaculous@googlegroups.com
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