Управление значением 'this' в событии jQuery

Я создал "control" с помощью jQuery и использовал jQuery.extend, чтобы помочь сделать его как OO насколько возможно.

Во время инициализации моего контроля я подключаю различные события кликов, например,

jQuery('#available input', 
            this.controlDiv).bind('click', this, this.availableCategoryClick);

Обратите внимание, что я pasing 'this' как аргумент данных в методе связывания. Я делаю это, чтобы получить данные, прикрепленные к экземпляру элемента управления, скорее из элемента, который запускает событие click.

Это работает отлично, однако я подозреваю, что есть лучший способ

Используя Prototype в прошлом, я помню синтаксис привязки, который позволял вам контролировать, что в нем было значение 'this'.

Что такое jQuery?

Ответ 1

Вы можете использовать jQuery.proxy() анонимную функцию, немного неудобно, что "контекст" является вторым параметром.

 $("#button").click($.proxy(function () {
     //use original 'this'
 },this));

Ответ 2

Мне нравится ваш путь, на самом деле используют аналогичную конструкцию:

$('#available_input').bind('click', {self:this}, this.onClick);

и первая строка this.onClick:

var self = event.data.self;

Мне нравится этот путь, потому что тогда вы получаете как элемент, щелкнутый (как этот), так и объект "this" как сам, без необходимости использования закрытий.

Ответ 3

jQuery имеет метод jQuery.proxy (доступен с версии 1.4).

Пример:

var Foo = {
  name: "foo",

  test: function() {
    alert(this.name)
  }
}

$("#test").click($.proxy(Foo.test, Foo))
// "foo" alerted

Ответ 4

Я не думаю, что у jQuery есть встроенная функция для этого. Но вы можете использовать вспомогательную конструкцию, как показано ниже:

Function.prototype.createDelegate = function(scope) {
    var fn = this;
    return function() {
        // Forward to the original function using 'scope' as 'this'.
        return fn.apply(scope, arguments);
    }
}

// Then:
$(...).bind(..., obj.method.createDelegate(obj));

Таким образом, вы можете создавать динамические "функции-обертки" с помощью createDelegate(), которые вызывают метод с данным объектом как область 'this'.

Пример:

function foo() {
    alert(this);
}

var myfoo = foo.createDelegate("foobar");
myfoo(); // calls foo() with this = "foobar"

Ответ 5

вы можете использовать метод javascript bind:

var coolFunction = function(){
  // here whatever involving this
     alert(this.coolValue);
}

var object = {coolValue: "bla"};


$("#bla").bind('click', coolFunction.bind(object));

Ответ 6

HTML-совместимые браузеры обеспечивают метод привязки на Function.prototype, который, пожалуй, самый чистый синтаксис и не зависит от структуры, хотя он не встроен в IE до IE 9. (Существует polyfill для браузеров без него.)

На основе вашего примера вы можете использовать его следующим образом:

jQuery('#available input', 
        this.controlDiv).bind('click', this.availableCategoryClick.bind(this));

(боковое примечание: первый bind в этом выражении является частью jQuery и не имеет ничего общего с Function.prototype.bind)

Или использовать немного более сжатый и обновленный jQuery (и устранить путаницу из двух разных типов bind s):

$('#available input', this.controlDiv).click(this.availableCategoryClick.bind(this));

Ответ 7

jQuery не поддерживает привязки, и предпочтительный способ - использовать функции.

Потому что в Javascript this.availableCategoryClick не означает вызов функции availableCategoryClick для этого объекта, jQuery советует использовать этот предпочтительный синтаксис:

var self = this;
jQuery('#available input', self.controlDiv).bind('click', function(event)
{
   self.availableCategoryClick(event);
});

Концепции OO в Javascript трудно понять, функциональное программирование часто проще и читабельнее.

Ответ 8

Увидев, что функции меняют область видимости, наиболее распространенным способом является выполнение этого вручную, с чем-то вроде var self = this.

var self = this

$('.some_selector').each(function(){
  // refer to 'self' here
}