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?
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.
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).
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);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With