2009-02-06 6 views
71

Я создал «элемент управления» с помощью jQuery и использовал jQuery.extend, чтобы помочь сделать его как OO максимально возможным.Управление значением «this» в событии jQuery

Во время инициализации моего контроля я телеграфировать различные события щелчка, как так

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

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

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

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

Что такое jQuery?

+0

Незнайка почему вы пытаетесь сделать JQuery OO, так как JQuery является более функциональным, чем OO. – cletus

ответ

98

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

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

Я не думаю, что у 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(), который называют метод с данным объектом, как его 'этой области видимости.

Пример:

function foo() { 
    alert(this); 
} 

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

Ребята, этот пост был написан в феврале 2009 года, в то время еще не было 'jQuery.proxy()' (появилось в v.1.4, январь 2010). Не нужно ниспровергать. –

+5

Разве это не лучший ответ на большинство голосов? Я благодарен, если устаревшие ответы опускаются - проголосовали или удалены. Это помогает избежать ошибочного поведения ИМХО. – ben

+1

Конечно, лучший ответ должен получить большинство голосов, как это имеет место здесь. Но это не означает, что ответы второго уровня должны быть пропущены. Это снижает репутацию и просто несправедливо. Что вы ожидаете от меня? Проверять и пересматривать мои древние ответы на регулярной основе? –

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 
} 
+0

соглашение говорит, что вы должны использовать 'that' вместо этого. – Orlando

36

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

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

и первую линию this.onClick:

var self = event.data.self; 

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

+0

Это на самом деле очень полезно, лучший подход, который я видел до сих пор. спасибо, чувак! –

+0

Удобное решение. Я люблю это. –

+0

Отличная идея, спасибо! –

32

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

Пример:

var Foo = { 
    name: "foo", 

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

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

вы можете использовать яваскрипт bind метода, как это:

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

var object = {coolValue: "bla"}; 


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

Увы, похоже, это только в JS 1.8.5, и это вырезает браузеры, такие как IE8. –

+1

@ Метод связывания LukeH - это просто код js .. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind – Orlando

+1

@JLRishe вы можете использовать этот [polyfill] (https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Compatibility) для IE8 – Orlando

4

HTML 5-совместимые браузеры обеспечивают bind method на 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));