在保留元素引用的同时将对象方法附加到事件

时间:2016-06-25 21:20:32

标签: javascript design-patterns javascript-events

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. 与上面相同,但不使用原型方法,而是使用内联函数。

  3. 我宁愿不使用内联函数,因为它会使代码混乱。如果我不需要,我宁愿不将对象实例作为参数传递。

    是否有更惯用,更简单的方法来实现这一目标?

3 个答案:

答案 0 :(得分: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.
};

这样,我不需要显式地将参数传递给事件处理函数,我也不需要使用内联函数。

答案 1 :(得分: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
};

答案 2 :(得分: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
};
相关问题