2016-06-25 3 views
1
function MyObject() { 
    this.name = ""; 
    this.elements = document.getElementsByClassName('myClass'); 
} 

MyObject.prototype.attachEventHandlers = function() { 
    for (var i = 0; i < this.elements.length; i++) { 
    this.elements[i].addEventListener('click', this.myEventHandler); 
    } 
}; 

MyObject.prototype.myEventHandler = function() { 
    // Here "this" referst to the element that the event invoked on: 
    console.log(this.innerHTML); 

    // Is there a way to get the name property like: 
    // console.log(this.name); 
    // without passing the instance as an argument? 
}; 

var myObject = new MyObject(); 
myObject.name = "Foo"; 
myObject.attachEventHandlers(); 

Я хотел бы использовать метод myEventHandler как даже обработчик, но, как вы знаете, в обработчики событий this относятся к элементу, что событие было вызвано на ,Прикрепления метод объекта к событию, сохраняя при этом опорный элемент

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

Есть два способа я могу думать:

  1. Передача экземпляра объекта в качестве аргумента в обработчик событий, как:

    // ... 
        var that = this; 
        this.elements[i].addEventListener('click', function() { 
         that.myEventHandler(that); 
        } 
    // ... 
    
    MyObject.prototype.myEventHandler = function(that) { // ... 
    
  2. То же самое, что и выше, но вместо используя метод прототипа, используя встроенную функцию.

Я бы предпочел не использовать встроенную функцию, поскольку она загромождает код. И я бы предпочел не передавать экземпляр объекта в качестве аргумента, если мне это не нужно.

Есть ли более идиоматический и простой способ достичь этого?

+0

'this.elements [i] .addEventListener ('click', function (e) {e.target.myEventHandler (e)});' – Redu

ответ

1

Вы можете вызвать bind метод на функцию обратного вызова:

MyObject.prototype.attachEventHandlers = function() { 
    for (var i = 0; i < this.elements.length; i++) { 
    this.elements[i].addEventListener('click', function (event) { 
     this.myEventHandler(event.target); 
    }.bind(this)); 
    } 
}; 

/* 
* @param {HTMLElement} element The element that has been clicked. 
*/ 
MyObject.prototype.myEventHandler = function(element) { 
    // ... 
    console.log(this); // MyOject 
}; 
+1

Эй, спасибо, я знал о 'bind', но didn ' t знать о 'Event.target'. Я не хочу явно передавать аргумент обработчику событий, поэтому я добавил свой собственный ответ, используя «Event.target». Спасибо, что указали! Я подтвердил ваш ответ. – hattenn

+0

Извините за неправильный ответ, я вообще не прочитал вопрос. –

+0

Эй, не беспокойтесь, вы уже много помогли! – hattenn

0

ИМХО лучшее решение заключается в использовании Function.prototype.bind():

this.elements[i].addEventListener('click', this.myEventHandler.bind(this.elements[i], this)); 

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

MyObject.prototype.myEventHandler = function(instance) { 
    console.log(this) // DOM element 
    console.log(instance) // class instance 
}; 
2

Я не знал о недвижимости Event.target. Спасибо @AlexandreThebaldi за указание на это.

// ... 
    this.elements[i].addEventListener('click', this.myEventHandler.bind(this)); 
// ... 

MyObject.prototype.myEventHandler = function(e) { 
    var el = e.target; 

    console.log(el) // Outputs the element. 
    console.log(this); // Outputs the object instance. 
}; 

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

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