2008-10-23 4 views
19

Есть ли в JavaScript эффективный или распространенный способ иметь класс в качестве обработчиков событий?Методы класса как обработчики событий в JavaScript?

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

<head> 
    <script language="javascript" type="text/javascript"> 

     ClickCounter = function(buttonId) { 
      this._clickCount = 0; 
      document.getElementById(buttonId).onclick = this.buttonClicked; 
     } 

     ClickCounter.prototype = { 
      buttonClicked: function() { 
       this._clickCount++; 
       alert('the button was clicked ' + this._clickCount + ' times'); 
      } 
     } 

    </script> 
</head> 
<body> 
    <input type="button" id="btn1" value="Click me" /> 
    <script language="javascript" type="text/javascript"> 
     var btn1counter = new ClickCounter('btn1'); 
    </script> 
</body> 

Обработчик события buttonClicked будет вызываться, но член _clickCount недоступен, или это указывает на какой-то другой объект.

Любые хорошие советы/статьи/ресурсы по этим проблемам?

ответ

17
ClickCounter = function(buttonId) { 
    this._clickCount = 0; 
    var that = this; 
    document.getElementById(buttonId).onclick = function(){ that.buttonClicked() }; 
} 

ClickCounter.prototype = { 
    buttonClicked: function() { 
     this._clickCount++; 
     alert('the button was clicked ' + this._clickCount + ' times'); 
    } 
} 
+0

Спасибо за ваше решение. Я также пытаюсь понять большую картину - образцы, практики и т. Д. Какие хорошие статьи вы знаете? – JacobE 2008-10-23 09:36:58

+5

эта вещь замечательная: http://ejohn.org/apps/learn/ – pawel 2008-10-23 09:49:46

5

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

Когда вам нужно событие элемента для запуска против конкретного экземпляра объекта (а-ля делегата в .NET), то вам нужно закрыть: -

function MyClass() {this.count = 0;} 
MyClass.prototype.onclickHandler = function(target) 
{ 
    // use target when you need values from the object that had the handler attached 
    this.count++; 
} 
MyClass.prototype.attachOnclick = function(elem) 
{ 
    var self = this; 
    elem.onclick = function() {self.onclickHandler(this); } 
    elem = null; //prevents memleak 
} 

var o = new MyClass(); 
o.attachOnclick(document.getElementById('divThing')) 
0

я не знаю почему Function.prototype.bind здесь не упоминалось. Так что я просто оставлю это здесь;)

ClickCounter = function(buttonId) { 
    this._clickCount = 0; 
    document.getElementById(buttonId).onclick = this.buttonClicked.bind(this); 
} 

ClickCounter.prototype = { 
    buttonClicked: function() { 
     this._clickCount++; 
     alert('the button was clicked ' + this._clickCount + ' times'); 
    } 
} 
1

Вы можете использовать синтаксис жира со стрелкой, которая связывается с лексической области видимости функции

function doIt() { 
    this.f =() => { 
    console.log("f called ok"); 
    this.g(); 
    } 
    this.g =() => { 
    console.log("g called ok"); 
    } 
} 

После этого вы можете попробовать

var n = new doIt(); 
setTimeout(n.f,1000); 

Вы можете попробовать его на babel или если ваш браузер поддерживает ES6 по телефону jsFiddle.

К сожалению, ES6 Class -syntax, похоже, не позволяет создавать функцию, лексически привязанную к этому. Я лично думаю, что это тоже может сделать. EDIT: Кажется, experimental ES7 feature to allow it.

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