Керування значенням 'this' у події jQuery


74

Я створив "елемент керування", використовуючи jQuery, і використовував jQuery.extend, щоб допомогти зробити його максимально можливим.

Під час ініціалізації мого контролю я підключаю різні події клацання, подібні до цього

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

Зверніть увагу, що я вставляю 'this' як аргумент даних у методі bind. Я роблю це для того, щоб отримати доступ до даних, приєднаних до екземпляра управління, а не з елемента, який запускає подію клацання.

Це працює чудово, проте я підозрюю, що є кращий спосіб

Раніше я використовував прототип, я пам’ятаю синтаксис прив’язки, який дозволяв вам контролювати значення значення „this” у події.

Що таке спосіб jQuery?


Не знаю, чому ви намагаєтесь зробити jQuery OO, оскільки jQuery є більш функціональним, ніж OO.
cletus

Відповіді:


104

Ви можете використовувати jQuery.proxy()з анонімною функцією, лише трохи незручно, що "контекст" є другим параметром.

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

39

Мені подобається ваш спосіб, насправді використовуйте подібну конструкцію:

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

і перший рядок this.onClick:

var self = event.data.self;

Мені подобається цей спосіб, тому що тоді ви отримуєте як елемент, що клацнув (як цей), так і об’єкт „це” як самостійно, без необхідності використовувати закриття.


це насправді дуже корисно, найкращий підхід, який я бачив на даний момент .. дякую чувак!
Євген Кузьменко

Акуратний розчин. Я це люблю.
Gad D Lord

ВИ розумні, як я :-D
peterchaula

Це найкраще. Ніякого додаткового складного коду закриття. Дякую
Kannan J

33

jQuery має jQuery.proxyметод (доступний з 1.4).

Приклад:

var Foo = {
  name: "foo",

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

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

21

Я не думаю, що 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"

40
Хлопці, цей пост був написаний у лютому 2009 року, на той час його jQuery.proxy()ще не було (з’явився у версії 1.4, січень 2010 року). Не потрібно голосувати проти.
Фердинанд Бейер

5
Чи не в тому, щоб дати найкращі відповіді найбільше голосів? Я вдячний, якщо застарілі відповіді проголосували або видалили. Це допомагає уникнути помилкових помилок IMHO.
ben

1
Звичайно, найкраща відповідь повинна набрати найбільше голосів, як це має місце тут. Але це не означає, що за найкращі відповіді слід відмовитись. Це знижує репутацію і просто не є справедливим. Що ти очікуєш від мене робити? Регулярно перевіряти та переглядати мої давні відповіді?
Фердинанд Бейер,

1
Ні. Я ні в якому разі не стверджую, що ви зробили щось погане. ІМХО цей сценарій просто недостатньо охоплений механізмами SO (принаймні AFAIK). Відповіді, які в один момент були дуже придатними, були проголосовані і залишаються там, навіть якщо вони з часом розвиваються непридатними, оскільки з’явилися інші методи, які перевершують старі механізми. ІМХО було б найкращим, якби можна було позначити ці відповіді таким чином, щоб або автор отримував повідомлення, і він міг відреагувати, або щоб було вказано, що відповідь може бути застарілою.
бен

4
@ben: Відповіді можуть бути застарілими, але це не причина позбавляти автора кредиту, який він заробив, коли відповіді були актуальними. Я думаю, що пропонувати функцію позначення застарілих відповідей краще, ніж голосувати вниз, що було колись правильною відповіддю.
Майк Перселл,

5

HTML 5-сумісні браузери забезпечують спосіб зв'язування на Function.prototypeяке, ймовірно , найчистіший синтаксис і не є каркасного залежним, хоча вона не вбудована в IE до IE 9. (Існує polyfill для браузерів без нього, хоча.)

На основі вашого прикладу ви можете використовувати його так:

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

(примітка: перша bindв цьому твердженні є частиною jQuery і не має нічого спільного з цим Function.prototype.bind)

Або використовувати трохи більш стислий і сучасний jQuery (і усунути плутанину з-поміж двох різних типів bind):

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

4

Ви можете використовувати метод прив'язки javascript таким чином:

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

var object = {coolValue: "bla"};


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

На жаль, це, здається, лише в JS 1.8.5, і це виключає браузери, такі як IE8.
Luke H

1
Метод прив'язки @LukeH - це лише якийсь js-код. Developer.mozilla.org/en-US/docs/JavaScript/Reference/…
Орландо,

1
@JLRishe, ти можеш використовувати цей поліфіл для IE8
Орландо,

@Orlando Ви справді маєте рацію. Зараз я збираюся видалити свій попередній коментар.
JLRishe

2

jQuery не підтримує прив'язки, і найкращим способом є використання функцій.

Оскільки в Javascript this.availableCategoryClick не означає виклик функції availableCategoryClick для цього об’єкта, jQuery радить використовувати такий бажаний синтаксис:

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

Поняття OO в Javascript важко зрозуміти, функціональне програмування часто простіше і читабельніше.


1

Побачивши, що функції змінюють обсяг, найпоширеніший спосіб - це зробити вручну, дещо на зразок var self = this.

var self = this

$('.some_selector').each(function(){
  // refer to 'self' here
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.