Закрытие вокруг переменной в обработчике события - PullRequest
1 голос
/ 31 мая 2011

Я знаю, что есть умный способ использовать замыкания и делать то, что я ищу, но я не уверен, что это такое.

В следующем коде:

var MyApp = {
  innerObject : {
    myData : "test value",
    myMethod : function() {
      // 'this' ends up referring to HTMLElement, not what I want 
      alert(this.myData);
    }
  }
  open : function() {
    document.getElementById('connectLink').addEventListener('click', this.innerObject.myMethod, false);
  }
}
MyApp.open();

Я хочу прикрепить обработчик события к элементу с id = 'connectLink' к методу внутри innerObject. Этот метод обращается к другим данным внутри innerObject для выполнения своей функции. Я знаю, что это как-то связано с хитрой природой ключевого слова this в javascript. Есть шаблон, который я могу принять, чтобы исправить это?

Ответы [ 2 ]

2 голосов
/ 31 мая 2011

Обратите внимание, что по соглашению идентификаторы, начинающиеся с заглавной буквы, представляют конструкторы.

Помните, что this устанавливается вызовом, а не объявлением или инициализацией (за исключением ES 5 bind *)1005 *, который еще не готов к использованию в обычной сети).

Вы можете сделать:

myMethod : function() {
      alert(MyApp.innerObject.myData);
}

Или вы можете создать MyApp , используя шаблон модуля , чтобы сохранить ссылку на innerObject (есть , которые думают, что это злоупотребляют ).Но даже в этом случае this внутри слушателя будет ссылаться на элемент, на который он установлен.

1 голос
/ 31 мая 2011

Сохраните ссылку на this и передайте анонимную функцию:

var self = this;
document.getElementById('connectLink').addEventListener('click', function() {
    self.innerObject.myMethod();
}, false);

Также помните, что вы должны использовать attachEvent в IE.

Обновление:

Более новые браузеры предоставляют .bind(), который позволяет вам связать контекст функции с определенным объектом. Это, наверное, самое чистое решение. Ссылка выше предоставляет реализацию для браузеров, которые ее не поддерживают.

el.addEventListener(
    'click', 
    this.innerObject.myMethod.bind(this.innerObject), 
    false
);
...