Передача контекста в обработчики событий в jQuery

Обычно для того, чтобы this указывал не на тот объект, который вызвал событие, а на тот, из которого навесили обработчик, делается примерно так:

var obj = {
  message: 'Hullo!',
  init: function() {
    var this_ = this;
    $('.button').click(function() {
      this_.handler(42);
    });
  },
  handler: function(num) {
    alert(this.message + '\n' + num);
  }
};
obj.init();

В jQuery есть правильный способ это сделать — метод jQuery.proxy():

$('.button').click(
  $.proxy(function() {
    this.handler(42);
  }, this)
);

Однако, если в метод нужно передать параметры, то короче от этого не станет, всё равно придётся создавать замыкание. Вот если бы параметров не было, получилось бы просто и красиво:

$('.button').click($.proxy(this.handler, this));

Но есть и более краткий способ передать и контекст, и параметры — через параметр data методов eventname():

$('.button').click(this, function(e) {
  e.data.handler(42);
});

К сожалению, этот способ работает начиная с jQuery 1.4.3, в более раниих версиях нужно использовать bind(), что несколько длиннее и не так красиво.

Дополнение. Когда-нибудь наступит светлое будущее, и можно будет пользоваться нативным методом bind. Вот так:

$('.button').click(this.handler.bind(this));

Или с параметром:

$('.button').click(this.handler.bind(this, 42));

Уже сейчас метод bind работает в последних версиях всех браузеров (включая IE9). Полифил для старых браузеров есть на MDN по ссылке выше. А если вы используете Modernizr, то полифил у вас уже есть.

Вы можете улучшить этот пост, отредактировав его на Гитхабе.

Обо мне

Я живу в Берлине и работаю фронтенд-разработчиком в Вэйфейре, а в свободное время фотографирую, глажу своих собак и пью кофе.

Читайте обо мне на моём сайте и подписывайтесь на мой блог о фотографии и твитер.