Do I have to clear events from the DOM if an element is removed?
Let's say I have a page that loads pages dynamically. As each page loads into the DOM, events for the elements in that page are added.
If the user loads another page, the elements loaded previously will be removed from the DOM. Naturally, because the elements themselves no longer exist, any events mapped to those elements cease to function.
However, are they also removed? Or are they sitting in the user's memory, taking up space?
Follow-up: Were a function defined as such:
var event = $('foobar').addEvent('click', function() {
alert(1);
});
One could easily remove the event with event = null
(or so I'd assume!)...
but w开发者_如何学Chat if the event were not saved to a local variable?
$('foobar').addEvent('click', function() {
alert(1);
});
Thanks!
first of all. what? this makes no sense:
var event = $('foobar').addEvent('click', function() {
alert(1);
});
it does not save the event into a local variable as you seem to think. it saves a reference to the foobar element object
into the event
variable - most mootools element methods will return this
for chaining, which is the element itself and not the result of the method (unless it's a getter like '.getStyle').
it then depends on how you get rid of the element what happens next. first off, element.destroy
, found here: https://github.com/mootools/mootools-core/blob/master/Source/Element/Element.js#L728
it will remove the element from the dom and from memory, and empty it in a safe way. it will be reliant on the browser's GC to clean up once it's gone, mootools won't do any spectacular GC for you for the element itself but it does run the special clean
function on the child nodes as well: var children = clean(this).getElementsByTagName('*');
.
the clean method also gets rid of any event handlers and storage attached to the child elements of the div.
THEN. events added by mootools go into element storage. Element storage is in an object behind a closure which the element proto uses. To test it, we will re-implement it and make it puncturable (a global object called storage) so we can check what happens to the reference after the parent is gone:
http://jsfiddle.net/dimitar/DQ8JU/
(function() {
var storage = this.storage = {}; // make it puncturable
var get = function(uid){
return (storage[uid] || (storage[uid] = {}));
};
Element.implement({
retrieve: function(property, dflt){
var storage = get($uid(this)), prop = storage[property];
if (dflt != null && prop == null) prop = storage[property] = dflt;
return prop != null ? prop : null;
},
store: function(property, value){
var storage = get($uid(this));
storage[property] = value;
return this;
},
eliminate: function(property){
var storage = get($uid(this));
delete storage[property];
return this;
}
});
})();
// read it.
var link = document.getElement("a");
var uid = link.uid; // will reference the mootools unique id for it
// add an event handler
link.addEvent("click", function(e) {
console.log("hi");
this.destroy();
// see what's left in storage for that element.
console.log(storage[uid]);
// storage should be empty.
console.log(storage);
});
link.getFirst().addEvent("mouseenter", function() {
console.log("over");
});
// check to see if it is there via element storage API.
console.log(link.retrieve("events").click);
// check to see if it's there via our puncture
console.log(this.storage[uid]);
// see all events in storage, inc child element:
console.info(this.storage);
what all this proves is, mootools cleans up all you need cleaned. as long as you don't use any inline onclick=
stuff on elements you work with, you're going to be fine. Between mootools' garbage collection and the browser, you are well covered. just be aware you can stack up multiple events on a single element if the callbacks are anonymous.
Interesting question... have a read of this: https://developer.mozilla.org/en/DOM/element.addEventListener#Memory_issues
To remove the event listener using jQuery, see http://api.jquery.com/unbind/
I have found that older versions of IE seems to have issues with adding and removing lots of elements with events binded to them. The main cause is circular references that cannot be garbage collected. You can find more information here: http://msdn.microsoft.com/en-us/library/Bb250448
Setting to null will not remove the event, it would just remove the reference to the event. You need to use both element.removeEventListener and element.detachEvent (depending on browser), or if you are using jquery unbind should work.
Also, there are tools available to detect leaks, this one works well (according to coworker): http://blogs.msdn.com/b/gpde/archive/2009/08/03/javascript-memory-leak-detector-v2.aspx
精彩评论