0,0
рейтинг
30 октября 2013 в 09:41

Разработка → Где 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
Овчинников Вячеслав @ova777
карма
17,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (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;
      

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