JQuery эквивалент MooTools связывает (это)

Я пытаюсь переписать класс tooltip Mootools в JQuery, используя этот плагин класса. Когда мой класс создается, я присоединяю прослушиватель событий к целевой ссылке, которая будет исчезать во всплывающей подсказке.

В случае обратных вызовов JQuery назначает ключевое слово "this" целевому объекту события, поэтому для сохранения ссылки на свойства класса, который я использую apply(), для установки "this" означает экземпляр класса. Это, по-видимому, аналог функции JQuery Mootools handy bind().

К сожалению, когда я использую apply(), я теряю параметр события обратного вызова. Например, в этом бите я получаю сообщение "e is undefined" во второй строке.

this.target.bind('click', function(e){
    e.preventDefault();
    var tip = this.opts.tip;
    tip.fadeOut(500, function(){
        tip.bind('click', function(){
            showing = false;
        })
    });
}.apply(this))

Я пропустил трюк здесь? Кто-нибудь знает способ решения этой проблемы?

Спасибо Фред

Ответ 1

TBH, mootools .bind, как вы его называете, просто Function.bind в ES5 - и доступен изначально в браузерах, поддерживающих js 1.8.5 + spec. MooTools только усиливает браузеры, у которых его еще нет, но позволяет встроенная реализация оставаться на прототипе - если она доступна.

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

Вы можете легко реализовать это как декоратор a Function.prototype.bind, если он не доступен изначально и использовать его в качестве примера выше:

// Function.prototype.bind polyfill
if ( !Function.prototype.bind ) {

  Function.prototype.bind = function( obj ) {
    if(typeof this !== 'function') // closest thing possible to the ECMAScript 5 internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');

    var slice = [].slice,
        args = slice.call(arguments, 1), 
        self = this, 
        nop = function () {}, 
        bound = function () {
          return self.apply( this instanceof nop ? this : ( obj || {} ), 
                              args.concat( slice.call(arguments) ) );    
        };

    bound.prototype = this.prototype;

    return bound;
  };
}

Как вы можете видеть, это немного больше, чем просто .apply/.call

Следует учитывать, что если вам нужно использовать bind или вы можете сохранить ссылку вместо этого.

например.

var self = this;
this.target.bind("click", function(e) {
    var tip = self.opts.tip;
});

это имеет меньший размер, чем привязка функции. он также дает вам правильную ссылку на this в качестве триггерного элемента (event.target === this). вы обнаружите этот шаблон гораздо чаще в mootools-core, чем привязанный, хотя привязка часто требуется, когда вы хотите назначать события методам класса, например:

this.element.addEvents({
    click: this.showTip.bind(this),
    mouseleave: this.hideTip.bind(this)
});

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

var self = this;
this.element.addEvents({
    click: function(e) {
        self.showTip(e);
    }
});

Специальная реализация jQuery - proxy - http://api.jquery.com/jquery.proxy/

Ответ 2

Все события, которые сделаны на каком-либо элементе (например, 'click' является одним из них), должны иметь свойство target, указывающее на этот элемент

var $this = $(e.target); // $this will be the clicked element

JSFiddle