Современный фронтенд несётся скоростным поездом, в окнах мелькают es6, es7 es2015, react, redux и куча других пассажиров. И не везде этот поезд останавливается. Но на станциях по-прежнему полно …jQuery.
И сегодня понадобилось дополнить “чужой” обработчик события (для простоты пусть будет onClick) дополнительными проверками, которые “чужим” не предусмотрен:
jQuery('element').bind('click', function() {
   if (checkIt()) {
      doIt();
   }
});
В дополнение к checkIt() необходимо позвать ещё и testIt().
В простейшем случае обработчик события может быть именованной функцией и задача становится тривиальной:
// editable "original"
function clickHandler(event) {
   if (checkIt()) {
      doIt();
   }
}
jQuery('element').bind('click', clickHandler);
// custom code
jQuery('element').unbind('click').bind(function(e) {
  if (testIt()) {
     clickHandler(e);
  }
});
Но “чужой” код изменить нельзя, а значит обработчик события останется анонимной функцией. Как до неё добраться ?
Беглый поиск по исходникам jQuery помог найти недокументированный метод jQuery._data, который поможет добраться до скрытых в его недрах обработчиков события. Несмотря на наличие комментария:
_Never_ expose “private” data to user code (TODO: Drop _data, _removeData)
в интересующей меня ветке 1.xx, методы (вместе с комментарием) перекочевали в последнюю на данный момент версию 3.1, а значит я без риска и страха использую их и даже порекомендую вам сделать тоже самое, но всё же на ваш страх и риск, в похожей небезвыходной ситуации.
И так к делу:
// original HARDcode
jQuery('element').bind('click', function() {
   if (checkIt()) {
      doIt();
   }
});
// custom code
var originalClickHandler = jQuery._data( element ).events.click[0].handler; // save handler
jQuery('element')
  .unbind('click') // remove handler
  .bind('click', function(e) {
    if (testIt()) { // wrap old handler with custom logic
      originalClickHandler(e)
    }
  });
Буду надеятся что таким чудо{вищным} методом никому больше воспользоваться не придётся.

