8

I'm trying to figure out how the DOM keeps track of event handlers, whether bound by using jQuery, addEventListener, or by HTML attribute (e.g. onload="myFunc()").

I've read that jQuery uses the .data() way to store event handlers bound by jQuery... but what about the others? Where do they go? I know that Webkit's inspector tool shows the Event Listeners by inspecting an element in the Elements tab, but where is it getting that information?

Incidentally, in some testing using Chrome's web inspector, I used the console to replace a version of jQuery on a live site with a newer one by pulling in the <script> tag, thus overriding the jQuery and $ variables. Obviously, events bound using jQuery before the replacement were lost, because a new .data() interface was introduced in the process.

Those handlers which are "lost," however, are still bound to certain events because they actually end up being called when the event fires. Suppose I want to remove those entirely, or supersede them with my own handlers? This is why I'd like to know how to access the actual handlers wherever the DOM is keeping them... and without jQuery.

Matt
  • 22,721
  • 17
  • 71
  • 112
  • As far as I know, they are bound to the DOM elements themselves, which are stored in the global `window` variable. – JCOC611 Oct 05 '12 at 22:50
  • @JCOC611: DOM elements just exist in memory. `window` has some references to elements, but they are not "stored in `window`". – Felix Kling Oct 05 '12 at 22:52
  • @benqus: Not when `addEventListener` is used. – Felix Kling Oct 05 '12 at 22:54
  • @benqus: Unless they've recently changed it, jQuery's `.data()` actually has nothing to do with the HTML5 `element.dataset`. jQuery's is entirely a separate collection of data stored at `jQuery.cache`. It's linked by a serial number jQuery stores in an expando property directly on the element. – I Hate Lazy Oct 05 '12 at 22:55

1 Answers1

10

Regarding methods like addEventListener, they're not directly visible in regular JavaScript code. They're stored internally.


Regarding inline handlers, they're simply stored directly on the DOM Element, like a typical handler, so that this:

<a href="#" onclick='alert("foo");'>click</a>

effectively becomes this:

a_element.onclick = function(event) { alert("foo"); };

(Older IE doesn't include the event parameter in the function.)


Regarding jQuery, you're right that they're stored in .data(), or more accurately jQuery.cache.

But your handlers are never directly assigned to the element. jQuery assigns a single generic handler (using addEventListener or attachEvent, whatever's available) that you never see. When an event occurs, it looks at event.type, then looks up the element's .data() to see if there are handlers for that type, and if so, invokes them.


So if you have some script that is overwriting jQuery.cache, you've effectively orphaned those handlers. You can't remove a handler bound with addEventListener unless you have a reference to that handler. Since jQuery's generic handler was also stored in jQuery.cache, there's no way to unbind it unless you destroy the element itself.

I don't remember specifically if the generic handler has a reference to jQuery.cache or just a subset of it. The reference it does hold would have an impact on just how much leaky data there may be.

I Hate Lazy
  • 47,415
  • 13
  • 86
  • 77
  • Well phooey. I guess I'll have to get clever then, or go back to the drawing board. Thanks for the comprehensive answer. – Matt Oct 06 '12 at 04:48
  • 1
    @Matt: If you can grab a reference to `jQuery.cache` before it's overwritten, you should then be able to do some manual clearing of the data and handlers. If you have a reference to a specific element as well, you could look up its entry in the original `jQuery.cache`, and target that specific one, which would also let you find and remove the generic handler. Good luck. :) – I Hate Lazy Oct 06 '12 at 12:36
  • Brilliant! I'll give it a go. – Matt Oct 06 '12 at 14:04
  • In conjunction with this answer, I've found [this question](http://stackoverflow.com/questions/1436823/can-i-programmatically-examine-and-modify-javascript-event-handlers-on-html-elem) about how to replace event handlers on an object without having references to them. – Matt Oct 08 '12 at 14:10
  • @Matt: Be careful. If you do that, make sure you've cleared all `jQuery.cache` data related to the element and its descendants. The only link between an element and its entry in `jQuery.cache` is a serial number jQuery stores in a property on the element. If you destroy and replace the element(s), that serial number is lost and all related data is orphaned. – I Hate Lazy Oct 08 '12 at 14:29
  • Please comment on this. https://stackoverflow.com/questions/53758066/using-ajax-only-for-whole-website-optimal-or-not – techie_28 Jun 03 '19 at 06:42
  • There is a HTML page whose central section gets a new HTML along with JS(via content scripts) which has the related event handlers etc. The new HTML gets replaced over & over in the central section,does this mean the handler & other things of the related JS(content script) also get erased? – techie_28 Jun 03 '19 at 06:46