Где jQuery хранит обработчики событий

    В «интернетах» я не нашел подробного ответа на этот вопрос. Как правило, рекомендуется использовать стандартный метод для получения обработчиков:
    $(elem).data('events')
    

    Но в моем случае он работать не хотел, поэтому пришлось немного разобраться в коде jQuery и найти где же все-таки они хранятся.

    Итак, начнем по порядку.

    1. Все данные по событиям в jQuery хранятся в переменной jQuery.cache
    Если мы туда заглянем, то увидим, что это простой массив объектов:
    image
    Номера элементов в массиве — это id`шки конкретных объектов, к которым относятся эти данные.
    Так как узнать какой id, например, у объекта document?

    2. id объекта jQuery сохраняет внутри самого объекта в специальной переменной, название которой генерируется при инициализации jQuery.
    И хранится она в jQuery.expando. Таким образом, id объекта можно узнать следующим образом:
    elem[ jQuery.expando ]
    

    3. Теперь мы знаем, что данные для объекта хранятся в jQuery.cache, и знаем как получить id объекта. Получаем данные jQuery для нашего объекта:
    jQuery.cache[ elem[ jQuery.expando ] ]
    

    Чтобы получить события — нужно обратиться к events полученного выше объекта:
    jQuery.cache[ elem[ jQuery.expando ] ].events
    

    4. Далее, получить массив с объектами, где хранятся обработчики событий, например для 'keydown', можно следующим образом:
    jQuery.cache[ elem[ jQuery.expando ] ].events['keydown']
    

    5. Получаем массив объектов, в каждом из которых есть метод handler — это и есть наши обработчики событий:
    image

    В качестве примера — выведем установленные обработчики на 'keydown' для объекта document:
    var events = jQuery.cache[ document[ jQuery.expando ] ].events['keydown'];
    for(var i=0; i<events.length; i++) {
        console.log( events[i].handler );
    }
    

    Результат:
    image
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 13
    • +3
      > в моем случае он работать не хотел
      Правильно так:
      $._data(document, "events")
      
      • +1
        Ну я бы не сказал, что это однозначно правильно (и что это неправильно тоже бы не сказал), т.к. даже если заглянуть в код jQuery:
        // For internal use only.
        _data: function( elem, name, data ) {
            return jQuery.data( elem, name, data, true );
        },
        

        То мы увидим, что во-первых комментарий к этой функции: «For internal use only», а во-вторых она все равно вызывает jQuery.data
      • 0
        > $(elem).data('events')

        Странно, а у вас какой версии jQuery?
        • 0
          1.8+ (см. release notes, поиск по _data).
          • 0
            Я про тоже хотел написать :)
          • +3
            jQuery версии 1.4.2, и, в принципе то, он работать должен, просто я пишу приложение под SmartTV, где требуется использовать именно jQuery, который записан в телевизор. И даже при том, что это 1.4.2, на некоторых старых телевизорах работает он все равно не совсем правильно, т.к. браузер в телевизоре — это как IE7, только со своими причудами.
            • +4
              jQuery записан в телевизор
              Будущее здесь.

              А как насчет работы с этими обработчиками? И есть ли возможность через этот массив грубо говоря, повесить обработчик на обработчик?
              Извините если глупость спросил, но иногда такая задача возникает, особенно при работе со сторонними плагинами.
              • +4
                теперь я знаю правильный ответ: обработчики событий jQuery хранит в телевизоре.
          • +1
            Спасибо, очень интересная статья.
            Просто хочу оставить здесь ссылку на Visual Event: www.sprymedia.co.uk/article/Visual+Event (визуализация обработчиков jQuery). Возможно кто-то не знает.
            P.S.: Полагаю, что конкретно в вашем случае он вероятнее всего не помог бы.
            • +4
              Этот кусок немного про другое.
              $(elem).data('events');
              

              Это если у нас есть элемент
              <div data-events="foo"></div>
              

              То выполнив
              $('div').data('events');
              

              Мы получим результат foo

              Это я так, для справки, т.к. в статье ничего не написано о том что на самом деле делает строчка кода из самого начала статьи.
              • +1
                Да, в вашем случае так и будет.
                Но, если элементу не прописать «data-events», то
                $('div').data('events');
                вернет именно объект с обработчиками.
                Способ получения обработчиков, описанный в самом начале статьи подходит, например, для получения обработчиков для объекта «document», т.к. врятли вы ему пропишите «data-events».

                А в вашем приведенном примере обработчики можно получить так:
                $._data( $('div').get(0) , 'events');
                
              • +4
                метод описанный автором показывает обработчики которые устанавливались с помощью jQuery.
                т.е. если повесить обработчик на чистом JS то его там не увидите
                • 0
                  Что логично, т.к. они просто так не могут оказаться в jQuery.cache. Но устанавливая обработчики нативными средствами можно добавить их в jQuery (но зачем?), например так:

                  var events = $.cache[document[$.expando]].events;
                  
                  events.nativeHandler = 1;
                  

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.