最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Where are attached event-handlers 'meta-data' stored? On the "DOM," object, or...

programmeradmin9浏览0评论

I've always wondered... so you have a code like this:

$('#click-me');

and you attach it with this:

$('#click-me').click(someFunction);

where is the 'meta-data' that says:

"Hey "jQuery-object #click-me," I will point you to 'someFunction' when you are clicked!"

I know that event-handlers can get destroyed such as my situation with Backbone.js where my events stopped firing due to me re-rendering the entire page, destroying some background functions/objects/Views along the way.. (this is the context as to why I'm asking this question)

NOW, MY QUESTION IS:

where are events 'meta-data' stored and how are they destroyed? Are they stored within the function that bound it to a function? Are they within the DOM 'meta-data' (if there is one) itself?

I'm trying to learn the intricacies of JavaScript because I'm tired of bugs. In addition to that, I'm wondering if I should watch out for garbage collection that might detach my events and such. Coming from C#, I would say JavaScript with the DOM is really something...

(also, as a side note, how can I access these events and 'debug' them? firefox? chrome?)


UPDATE

To say it in different words, where is the information that connects a DOM element to a certain event stored? DOM? Objects? (or.. does jQuery map it? does JavaScript have a 'meta-data'? it's around that context..

I've always wondered... so you have a code like this:

$('#click-me');

and you attach it with this:

$('#click-me').click(someFunction);

where is the 'meta-data' that says:

"Hey "jQuery-object #click-me," I will point you to 'someFunction' when you are clicked!"

I know that event-handlers can get destroyed such as my situation with Backbone.js where my events stopped firing due to me re-rendering the entire page, destroying some background functions/objects/Views along the way.. (this is the context as to why I'm asking this question)

NOW, MY QUESTION IS:

where are events 'meta-data' stored and how are they destroyed? Are they stored within the function that bound it to a function? Are they within the DOM 'meta-data' (if there is one) itself?

I'm trying to learn the intricacies of JavaScript because I'm tired of bugs. In addition to that, I'm wondering if I should watch out for garbage collection that might detach my events and such. Coming from C#, I would say JavaScript with the DOM is really something...

(also, as a side note, how can I access these events and 'debug' them? firefox? chrome?)


UPDATE

To say it in different words, where is the information that connects a DOM element to a certain event stored? DOM? Objects? (or.. does jQuery map it? does JavaScript have a 'meta-data'? it's around that context..

Share Improve this question edited Apr 7, 2022 at 18:21 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Feb 3, 2012 at 3:10 JC JCJC JC 12.1k11 gold badges44 silver badges63 bronze badges 2
  • I think my post answers both your questions. Tell me if anything isn't clear. – gideon Commented Feb 3, 2012 at 4:46
  • @gideon please don't edit his anymore because that's exactly what I meant.. see others who answered it.. I'm asking JavaScript & DOM and the 'meta-data' that connects these events, not the codes that jQuery uses to translate to attachEvent or addEventListener.. thank you. :) – JC JC Commented Feb 3, 2012 at 5:27
Add a ment  | 

4 Answers 4

Reset to default 5

Update : So I misunderstood the question, you wanted to know how events are bound in the context of just javascript and html. My original answer below describes how jquery creates and manages events. It boils down to a call to element.addEventListener.

From the MDN docs you see the eventtarget can be an element, the document, window or an XMLHttpRequest. From the w3 specifications on DOM Events an event target adds, removes and dispatches an event. So even information is probably stored in whatever is encapsulating things like elements, this will be implemented at the browser level.

From the issue you mentioned about copying and then replacing the html from the body erases the events, I'm thinking the browser just gives you the markup (without the event metadata) and then when you replace it, the metadata is gone. ( http://jsfiddle/qu9bF/1/)


Original answer: How jquery event handlers work.

Ok so I started digging this, for JQuery 1.4.2 (because I had to use a couple tools, all of which aren't updated)

Take a look first at this: http://james.padolsey./jquery/#v=1.4.2&fn=click

function (fn) {
    return fn ? this.bind(name, fn) : this.trigger(name);
}

That is how click is defined, it isn't actually defined in code. JQuery defines this function for all events/handler functions like below, yes! they are created/defined dynamically :

jQuery.each( ("blur focus focusin focusout load resize scroll unload click
            dblclick " +
        "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
        "change select submit keydown keypress keyup error").split(" "), 
    function( i, name ) {
        // the magic happens here..
        //each string is added as a function to the prototype
        jQuery.fn[ name ] = function( fn ) {
                return fn ? this.bind( name, fn ) : this.trigger( name );
        };//if a handler is NOT specified then attach an event OR call/trigger it

        if ( jQuery.attrFn ) {
                jQuery.attrFn[ name ] = true;
        }
});

From here on we need to look at bind, now bind() and one() are also defined like this. Search for "Code : bind and one events" here

From here I used chrome with this fiddle http://jsfiddle/qu9bF/ to step into the code. The block from c.each(["bind" is how the bind function is defined. The source is minified, but chrome can format it.

From here on the code calls JQuery.events.add, you can find this under the Events section here. This is not the add() that is documented I think

Toward the bottom, this piece of code is what does the magic. It accordingly calls element.addEventListener or attachEvent. See how it adds the on for attachEvent.

// Check for a special event handler
// Only use addEventListener/attachEvent if the special
// events handler returns false
if ( !special.setup || 
      special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
      // Bind the global event handler to the element
       if ( elem.addEventListener ) {
             elem.addEventListener( type, eventHandle, false );

        } else if ( elem.attachEvent ) {
             elem.attachEvent( "on" + type, eventHandle );
        }
 }

And there you have it! :) I hope it answered both your questions. You can link up to the non-minified versions of jquery source and step through it to figure things out. IMO sometimes IE9's debugger is more intuitive (that's the only thing I use it for), and use the pages I've mentioned to browse through the source sanely.

jQuery stores all the event binding and data cache on the jQuery.cache object. All the DOM nodes which were wrapped with jQuery and had events bound to them or data set will get automatically cleared when you are using jQuery html, empty, remove, replace etc.

That's why it's very important to never use innerHTML or other native DOM methods to insert/replace content that was altered before by jQuery. It will lead to leaks that you won't be able to cleanup unless you reset the jQuery.cache object manually.

There is also an undocumented method jQuery.cleanData which takes a collection of DOM nodes as an argument and it iterates over them and cleans up all their event bindings, data and removes references to these elements from the cache. This one can be useful if you have DOM fragments which were detached from the main DOM tree and there is a risk that they won't get cleaned up properly.

Regular events like click or submit (when not bound by jQuery) are actually just properties ('onclick', 'onsubmit') of the DOM elements themselves.

For jQuery events, the library keeps it's own record when you bind them and looks at it when you trigger them. jQuery puts all data about elements in a standard place, which you can access with $(e).data(). For events, it's just $(e).data('events').

You can unbind jQuery events with $().unbind(), and regular events using the delete keyword to delete the object's property which corresponds to the given event.

jQuery keeps its own map of element event handlers. There's rarely, very rarely, cause to worry about this unless you're abusing the library somehow.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论