David said:
David said:
Mychal Hackman wrote: [...]
Request : function(url, params, onsuccess, method){
var xhr = Ajax.transport,
res = '',
post = null;
xhr.onreadystatechange = function(){
I believe you have created a circular reference here.
Yes.
[xmlhttp]--readystatechange-->[anon function]-->[Activation Object]-->
[xmlhttp]
But this is unrelated to the previously mentioned (partial) chain.
There are two references to the XMLHttpRequest object: xhr and
Ajax.transport. Both are in scope of the function that is assigned to
onreadystatechange.
xhr has an onreadystatechange, which has xhr.
setting xhr = null will not solve the problem here. onreadystatechange
has Ajax.transport in scope chain.
That won't solve the problem because it will blow up in IE6.You have
to set it to a Function object (preferably an empty one).
Setting xhr = null won't blow up in IE. Setting xhr.onreadystatechange =
null will, but setting xhr = null won't.
That's correct. I misread.
Setting xhr won't break the circle, either. There is still
Ajax.transport in scope of the function assigned to xhr.onreadystatechange.
But setting onreadystatechange to an empty Function will. That's the
most important point.
Ajax.transport -> onreadystatechange -> [[Scope]] -> Ajax.transport.
No. Ajax is global. It's not referenced by the local Activation
Object. If it were, virtually everything would leak (think about it).
Identifier Ajax does not need to be referenced by the local activation
object. It is in the scope chain.
That's irrelevant. There's no circular reference in that case.
For example, if the onreadystatechange has an eval:-
xhr.onreadystatechange = function(){
if(Math.random > .999) {
eval("alert(typeof Ajax.transport)");
}
}
- it would still have to look up the scope chain and find
Ajax.transport. It makes no difference if the Ajax object is global.
Of course it does. Diagram it.
You seem to have a misunderstanding of how scope chain and identifier
resolution works.
The next object in scope chain of the function assigned in
onreadystatechange is the function object assigned to Ajax.Request the
next object in the scope chain after that is the containing scope, which
contains the Ajax object itself.
onreadystatechange handler Scope --> Ajax.Request Scope --> containing
scope (global?)
In fact, Ajax object does not have to be global at all.
As mentioned, that is irrelevant to the memory leak consideration.
Ah, not that is you failing to see the relevance, not me writing
irrelevance.
The Ajax.transport is in scope of the function assigned. If, for
example, the anonymous function body set xhr = null, then there would be
still one remaining link to the XMLHttpRequest object. That reference is
Ajax.transport.
[Global Scope]
Variable: Ajax
|
|
[Ajax.Request Scope]
Variable: xhr, res, post, url, params, onsuccess, method
|
|
[onreadystatechange handler Scope]
Variable: {empty}
Start from the bottom of the diagram, in onreadystatechange handler
Scope. The scope chain includes Ajax.Request Scope, and then the scope
above that (global, apparently, but it doesn't really matter). The last
object on the scope chain has a reference to Ajax.transport.
Ajax.transport is in the scope chain of onreadystatechange.