Man this is complex 
I just want to see if I start to understand...
So if that 'new Ajax.Request' is in a function, then that url variable will not be released until that ajax request successfully finishes and that onSuccess function runs?
What happens then when the ajax request is not successfull and throws an exception. That url value will stay in memory until you navigate away from the page?
What happens when you didn't only store a url string, but let's say a reference to a collection of 200 dom objects and the ajax request fails. Circular reference? Meaning a 'real' memory leak. That memory won't be released even after navigating away from the page.
Manu.
ps: Do you give private lessons? 
On Sat, Feb 23, 2008 at 2:37 PM, T.J. Crowder < tjcrowder  gmail.com" >tjcrowder gmail.com> wrote:
kangax: 
all: I should mention that I don't know for sure that this create-a- closure-within-a-closure idiom works in terms of the garbage
collectors out there; I've always intended to go find out because it seems like there's a chain involved and it wouldn';t necessarily be broken by doing that. I9;d be really interested in any references
folks have to empirical results on that, since as Manu points out, it might matter in terms of memory use. A quick-and-dirty test in FF2 for Windows suggests that FF doesn't release the context in this scenario:
var keeper = null; function executionContextTest() { var a; var n;
a = new Array(); for (n = 200000; n > 0; --n) { a[n] = new Date();
}
// keeper = function() { // alert('This is the keeper function39;); // };
keeper = (function() { return function() { alert('This is the keeper function39;);
} })(); }
(Where I trigger executionContextTest via a button.) The commented- out code would definitely preserve the execution context and therefore the array, but the second example is using the closure-creates-a-
closure idiom. FF seems to keep all of the execution contexts alive (and therefore preserve the array) in this case as well. When I run this, FF's memory use goes up by about 19MB, and doesn't come down
again until I use another button to release the keeper reference (and then an alert to jog the garbage collector). If I don't create the closure at all, the memory is reclaimed as soon as executionContextTest completes (without having to jog the garbage
collector).
But again, this was not in any way a scientific test. If anyone can point me at some... 
Manu: Don't let this bother you in cases where you're not keeping a reference to the closure, that's the only time the issue of keeping
the execution contexts alive comes up. Use-and-discard closures are not a problem (and very useful).
-- T.J. Crowder tj /crowder software / com
On Feb 23, 12:43 pm, kangax < kan...  gmail.com" >kan... gmail.com> wrote: > Wow, that's one thorough explanation. > Thanks T.J. > > On Feb 23, 5:01 am, "T.J. Crowder" < tjcrow... gmail.com">tjcrow... gmail.com> wrote:
> > > Hi, > > > > Closures is something that (can) cause memory leaks, right? > > > That's a complex topic. Closures inherit, and therefore preserve > > for their lifecycles, all of the local variables and parameters of the
> > functions they're defined in. If the closure is used immediately and > > discarded, you don't much care. If you're going to retain a reference > > to the closure (for instance, an event handler, or a dynamically-
> > created instance method), then you want to be aware of this. Here's > > an example of the latter case: > > > function myNiftyMethod(param) > > { > > var v1, v2, v3;
> > > // ... do something ... > > > // create and retain a closure to do something > > this.thingy = function() { > > // ... some code for the closure ...
> > }; > > > } > > > When myNiftyMethod is executed, it creates a closure and remembers it > > on the object instance as this.thingy. Since the closure holds a > > reference to all of myNiftyMethods local variables and params (even
> > though it doesn't use them), and since the object instance keeps a > > reference to the closure, 'param', 'v19;, 'v29;, and 'v39; all live on > > for as long as the closure does. (Modulo cool JavaScript engine
> > optimisations, which I don't think are common yet and are harder for > > the engine to do than it would at first seem.) > > > So closures can have memory *implications*; if you understand how they
> > work, though, and get used to some idioms around them, you won't cause > > memory leaks (barring JavaScript engine bugs). > > > This is rambling a bit, but here's an example of the case where you're
> > using the closure immediately and discarding it: > > > function myNiftyMethod(someArray) > > { > > var v1, v2, v3; > > > // ... do something ... >
> > // create and retain a closure to do something > > someArray.each(function(item) { > > item.doSomethingCool(); > > }); > > > } > > > You don't keep a reference to the closure used in the each() method,
> > so you don't have to consider the implications of myNiftyMethod's > > parameters and variables being retained. And it's a very powerful and > > expressive way to deal with each item in the array.
> > > > - I'm getting lost in how you constructed the onSuccess callback... > > > That's easy to do. He39;s using a closure to construct and return > > another closure; it's the inner one that gets assigned to the
> > onSuccess handler and retained, the outer one is run immediately and > > discarded. If you look carefully at the code defining the onSuccess > > handler, you'll see that the entire outer closure is wrapped in parens
> > -- the opening paren is right after "onSuccess:", and then right at > > the end of the closure you see the closing paren followed by "(item)" > > -- that "(item)" tells you he's *executing* the outer closure right
> > then, not just creating it. When it runs, the outer closure creates > > the inner closure and returns it. *That's* what gets assigned to > > onSuccess, the reference to the inner closure. The outer closure has
> > only the param it needs (item) and no local variables, so the inner > > closure only preserves the information it really needs, not all of the > > local variables where all of this is running.
> > > Hope this helps, > > -- > > T.J. Crowder > > tj /crowder software / com > > > On Feb 23, 7:34 am, "Manu Temmerman-Uyttenbroeck" > > > < manu.temmermanuyttenbro... gmail.com">manu.temmermanuyttenbro... gmail.com> wrote:
> > > Hi, > > > > Closures is something that (can) cause memory leaks, right? > > > kangax, would you mind explaining in a bit more detail why you wrote the > > > code like you wrote it? I'm a bit lost in it. I restructured the code you
> > > wrote a bit...http://pastie.caboo.se/156248 > > > - Is there a reason why you don't write a ';'; after the new Ajax.Request > > > (...)? > > > - Is there a reason why you don't write a ';'; after the
> > > someArray.each(function(item) > > > { ... })? > > > - I'm getting lost in how you constructed the onSuccess callback... > > > > Thx... > > > > Manu.
> > > > On Fri, Feb 22, 2008 at 11:11 PM, kangax < kan... gmail.com">kan... gmail.com> wrote: > > > > > Looks like a closure issue to me (solved with another closure).
> > > > Also, is that an array you are iterating over using "for..in" ? > > > > > siteListArray.each(function(item) { > > > > var url = 'functions.php?command=numberOfErrors&site=9; + item;
> > > > new Ajax.Request(url, { > > > > onSuccess: (function(item) { return function(t) { > > > > $(39;sidebar_site_div_39; + item).update(t.responseText); > > > > }})(item)
|