Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can jQuery's click() function be so much faster than addEventListener()?

I'm sure we've all seen the site for vanilla-js (the fastest framework for JavaScript) ;D and I was just curious, exactly how much faster plain JavaScript was than jQuery at adding an event handler for a click. So I headed on over to jsPerf to test it out and I was quite surprised by the results.

jQuery outperformed plain JavaScript by over 2500%.

My test code:

//jQuery
$('#test').click(function(){
  console.log('hi');
});

//Plain JavaScript
document.getElementById('test').addEventListener('click', function(){
  console.log('hi');
});

I just can't understand how this would happen because it seems that eventually jQuery would end up having to use the exact same function that plain JavaScript uses. Can someone please explain why this happens to me?

like image 585
Aust Avatar asked Nov 15 '12 23:11

Aust


People also ask

What is the use of addEventListener in Javascript?

The addEventListener() method allows you to add event listeners on any HTML DOM object such as HTML elements, the HTML document, the window object, or other objects that support events, like the xmlHttpRequest object.


2 Answers

I think it's because internally jQuery really only has to call addEventListener() once, for its own internal handler. Once that's set up, it just has to add your callback to a simple list. Thus most of the calls to .click() just do some bookkeeping and a .push() (or something like that).

like image 134
Pointy Avatar answered Sep 27 '22 23:09

Pointy


As you can see in this snippet from jQuery.event.add it does only create the eventHandle once.
See more: http://james.padolsey.com/jquery/#v=1.7.2&fn=jQuery.event.add

 // Init the element's event structure and main handler, if this is the first
events = elemData.events;
if (!events) {
    elemData.events = events = {};
}
eventHandle = elemData.handle;
if (!eventHandle) {
    elemData.handle = eventHandle = function (e) {
        // Discard the second event of a jQuery.event.trigger() and
        // when an event is called after a page has unloaded
        return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? jQuery.event.dispatch.apply(eventHandle.elem, arguments) : undefined;
    };
    // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
    eventHandle.elem = elem;
}

And here we have the addEventListener:

    // Init the event handler queue if we're the first
    handlers = events[type];
    if (!handlers) {
        handlers = events[type] = [];
        handlers.delegateCount = 0;

        // 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);
            }
        }
    }
like image 20
Andreas Louv Avatar answered Sep 28 '22 01:09

Andreas Louv