addEventListener и область этого - PullRequest
9 голосов
/ 26 ноября 2009

У меня есть сторонний флеш-объект, которым я могу манипулировать с помощью предоставленного ими javascript API. Я пытаюсь прослушать событие на этом объекте, а затем запустить событие внутри моего объекта, чтобы еще больше раздувать событие. Я использую EXT Js, но не думаю, что это важно здесь.

Пример кода

this.chart.addEventListener('create', function() {
    this.fireEvent('created');
}, false)

Моя проблема в том, что «this» внутри анонимной функции относится к объекту, который вызвал событие, а не к моему объекту, на котором я хочу запустить событие.

Это еще одна проблема. Заранее спасибо за любую помощь.

Ответы [ 3 ]

13 голосов
/ 26 ноября 2009

А как насчет создания внешней переменной перед ссылкой на объект 'this'. Например:

var _this = this;
this.chart.addEventListener('create', function() { _this.fireEvent('created'); }, false)
5 голосов
/ 24 марта 2013

В то время как другие ответы выполняют то, что вам нужно, они не работают наиболее эффективным (масштабируемым) способом, потому что они в конечном итоге не отделяют объект представления (this.chart) от логики этого представления (fireEvent()) , В приложениях MVC эти «решения» представления находятся в контроллере . Контроллер "контролирует" представления и должен содержать все API, к которым может обращаться представление.

В вашем примере this - это контроллер, и это нормально (это означает, что вы добавляете своих слушателей в нужном месте). Все, что вам действительно нужно сделать, это связать обработчик с областью действия, которое должно выполнять «обработку» - в вашем случае: this:

// `this` is the controller of `chart`
this.chart.addEventListener('create', function() {
    this.fireEvent('created');
}.bind(this));

То, что сделали другие ответы на этой странице, сделано так, что ваше представление становится его собственным контроллером, но только во время обработки событий create, путем назначения временной ссылки на «controller» с помощью var self = this. Опять же, это работает просто отлично, но не работает в масштабе в приложениях, управляемых событиями, и это не имеет смысла, если у вас много событий для обработки.

.bind() является реализацией ECMAScript 5. Если это необходимо для работы даже в более старых браузерах, хороший способ сделать это описан здесь (с использованием functions и .call()): https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind

1 голос
/ 26 ноября 2009

Это типичный подход к этой проблеме: -

(function(self) {
  self.chart.addEventListener('create', function() {self.fireEvent('created');}, false);
})(this);
...