2010-06-10 4 views
0

Следующий код не работает, как я интуитивно ожидать, что это:JQuery/JavaScript события - прототип обработчика событий

function MyObject(input) { 
    input.change(this._foo); 
    this.X = undefined; 
} 

MyObject.prototype._foo = function() { 
    alert("This code is never called"); 
    // but if it did 
    this.X = true; 
} 

var test_input = $("input#xyz"); // a random, existing input 

var m = MyObject(test_input); // attach handler (or try to) 

test_input.change(); // trigger event 

alert(m.X); // undefined 

Я бы ожидать, что _foo() будет называться (и, если это когда-нибудь случится, что this переменная _foo() будет конкретизацией MyObject.

кто-нибудь знает, почему это не работает, и любого альтернативного шаблона для передачи объекта в обработчик события?

Спасибо за чтение ING.

Brian

+0

Существуют существующие методы для добавления событий ('bind()', 'live()') и запуска событий ('trigger()') в jQuery. Я не уверен, что вы здесь делаете. Кроме того, мне кажется, что если вы хотите вызвать метод объектов, вам нужно называть его как 'this._foo()', а не 'this._foo', иначе вы выполняете назначение. Вполне возможно, что я вас не понимаю. – artlung

+0

Возможный дубликат [Как получить доступ к правильному \ 'this \'/context внутри обратного вызова?] (Http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside -a-callback) – Bergi

+0

Спасибо, Берги. Связанный с ним вопрос был задан через три года после того, как этот был закрыт, так что не будет ли дублирование на самом деле идти в другом направлении? Это неверно и, кажется, вводит в заблуждение, чтобы отметить этот вопрос как «уже ответивший» на вопрос, который возник через три года. Не будет ли этот вопрос дублировать этот вопрос? –

ответ

4

Как Кенни указывает, что вам не хватает new. Кроме того, необходимо убедиться, что this в _foo относится к MyObject экземпляра
Один из способов сделать это: -

function MyObject(input) { 
    var _this = this; 
    input.change(function() { 
     // explicitly set the `this` in _foo to `_this` 
     _this._foo.call(_this); 
    }); 
    this.X = undefined; 
} 

MyObject.prototype._foo = function(event) { 
    alert("This is called"); 
    // and 'this', being 'm', has X set to true 
    this.X = true; 
    // the textbox must be accessed by 'event.target' not 'this' if you need it 
} 

var test_input = jQuery("input#xyz"); // a random, existing input 

var m = new MyObject(test_input); // attach handler (or try to) 

test_input.change(); // trigger event 

alert(m.X); // true 

P.S Вы не можете избежать использования нового оператора, оставляя его! :)

2

Чтобы создать объект в Javascript, используйте new.

var m = new MyObject(test_input); // attach handler (or try to) 
+0

Я пытался избежать «новых», как предлагает Дуглас Крокфорд, но вы правы, указав хотя бы одну ошибку с кодом. :) –

+0

@Brian: Без использования 'new',' this' внутри 'MyObject' указывает на' window', а не на «экземпляр» MyObject. Я помещаю «экземпляр» в кавычки, так как, не желая использовать 'new', вы никогда не будете создавать экземпляры чего-либо. – Matt

1

Этот вопрос сейчас старый, но есть другое решение. Ваша проблема, как упоминалось выше, вы пропустили «новый», а ссылка «this» в обработчике событий всегда будет элементом, на котором было инициировано событие, а не объектом, обрабатывающим событие.

Поскольку вы используете JQuery, есть простой способ заставить это действовать так, как вы хотите. Используйте команду JQuery.proxy method, чтобы установить контекст обработчика события, чтобы использовать ваш объект как «это». В вашем примере, вы просто должны изменить строку

input.change(this._foo); 

в

input.change(jQuery.proxy(this, "_foo")); 

Дайте этому попытку, если вы снова столкнетесь с этой проблемой с JQuery.

Смежные вопросы