Как функция jQuery click() может быть намного быстрее, чем addEventListener()?

Я уверен, что мы все видели сайт для vanilla-js (самая быстрая фреймворк для JavaScript ); D и мне было просто любопытно, точно, насколько быстрее был обычный JavaScript, чем jQuery при добавлении обработчика события для клика. Таким образом, я отправился в jsPerf, чтобы проверить его, и я был весьма удивлен результатами.

jQuery превосходит обычный JavaScript более чем на 2500%.

Мой тестовый код:

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

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

Я просто не могу понять, как это произойдет, потому что кажется, что в конечном итоге jQuery в конечном итоге придется использовать ту же самую функцию, что и обычный JavaScript. Может кто-нибудь объяснить, почему это происходит со мной?

Ответ 1

Как вы можете видеть в этом фрагменте из jQuery.event.add, он только создает eventHandle один раз.
Подробнее: http://james.padolsey.com/jquery/#v=1.7.2&fn=jQuery.event.add

 // Init the element 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;
}

И здесь у нас есть 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);
            }
        }
    }

Ответ 2

Я думаю, это потому, что внутри jQuery действительно нужно только вызвать addEventListener() один раз для собственного внутреннего обработчика. После этого нужно просто добавить ваш обратный вызов в простой список. Таким образом, большинство вызовов .click() просто выполняют некоторую бухгалтерию и .push() (или что-то в этом роде).