Как я могу использовать метод класса в качестве обработчика onclick в JavaScript?

Рассмотрим следующий класс Javascript:

function ClassA() {
 this.someVariable = someValue;
 this.myHandler = function(){
   // I WANT TO CALL InnerFunction
   this.innerFunction();
 };

 this.innerFunction = function(){
   // do something that accesses/manipulates someVariable
 };

 this.hookUp = function(id){
   document.getElementById(id).onclick = this.myHandler;
 };
};
...
...
var button = document.createElement('button');
button.setAttribute('id','mybuttonid');
// append button to the document
...
...
var x = new ClassA();
x.hookUp('mybuttonid');

Когда я нажимаю кнопку, обработчик выполняется, однако «это» теперь относится к элементу кнопки, а не к объекту ClassA, поэтому он не может разрешить innerFunction().

Что мне нужно, так это способ указать обработчику, что контекст this является экземпляром ClassA (аналогично $.ajax({context: this....}), где вы можете использовать 'this' в . done() или .error()), или способ передать ссылку на экземпляр обработчику, не заставляя обработчик выполняться во время создания экземпляра. Например, если я попытаюсь передать «это» в качестве параметра myHandler (myHandler=function(ref){}, а затем изменить: document.getElementById(id).onclick = this.myHandler(this);) Но когда вы добавите параметры для myHandler, функция выполняется во время создания экземпляра класса, а не во время клика.

Любая помощь будет оценена.


person adaj21    schedule 27.10.2013    source источник
comment
Вместо this.someVariable попробуйте просто использовать var someVariable. someVariable будет доступно только в рамках функции, поэтому this не нужно. Кроме того, в JavaScript нет такой вещи, как классы, поэтому ваша идея использовать this может быть ошибочной.   -  person Ian Walker-Sperber    schedule 28.10.2013
comment
Спасибо .. возможно, я не очень ясно выразился, моя основная проблема заключается в доступе к innerFunction(). Я пытаюсь написать код, напоминающий ООП, чтобы его было легче понять и поддерживать, по крайней мере, для меня :).   -  person adaj21    schedule 28.10.2013


Ответы (3)


Заменять...

this.myHandler = function(){
    this.innerFunction();
};

... с ...

var self = this;
this.myHandler = function() {   
    self.innerFunction();
};

См. эту статью Крокфорда. Цитировать:

По соглашению мы делаем приватную переменную that. Это используется, чтобы сделать объект доступным для частных методов. Это обходной путь для ошибки в спецификации языка ECMAScript, которая приводит к неправильной установке this для внутренних функций.

См. также Что означает 'var that = this;' значит в JavaScript?

person Nils Lindemann    schedule 27.10.2013
comment
Вы, сэр, сэкономили мне часы поиска решений. Благодарю вас ! - person Diana Ionita; 18.02.2014

Как вы уже обнаружили, значение this зависит от того, как вызывается метод. Таким образом, использование this в обработчиках событий, прикрепленных к элементам DOM, может сбивать с толку.

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

Например, измените функцию подключения так:

this.hookUp = function(id) {
    var _this = this;
    document.getElementById(id).onclick = function() {
      _this.innerFunction();
    }
}

Обратите внимание, что вы больше не зависите от this внутри обработчика onclick и, таким образом, избегаете проблемы. Оказавшись в innerFunction, вы можете продолжать использовать this как обычно, так как теперь он правильно указывает на правильный объект.

Для более глубокого объяснения того, как this работает в функциях, в MDN есть хороший статья о ключевом слове this.

person zastrowm    schedule 27.10.2013
comment
Спасибо, полезно и понятно объяснил. - person umbe1987; 20.02.2019

это обычно решается с помощью так называемого «прокси-шаблона».

Я думаю, это поможет (-!

http://addyosmani.com/resources/essentialjsdesignpatterns/book/#proxypatternjquery

person user1566994    schedule 27.10.2013