无法从我自己的事件委托系统中删除事件

Cannot removing an event from my own event delegation system

我正在尝试编写自己的事件委托系统,它运行良好,只是一旦我将事件附加到元素就无法删除它!我一直在努力弄清楚这一点。任何帮助将不胜感激。

代码在笔中:http://codepen.io/anon/pen/BjyZyV?editors=101

下面还有:

标记

<ul id="parent">
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
</ul>

Javascript

Element.prototype.matches = Element.prototype.matches || Element.prototype.msMatchesSelector;

function isDescendant(parents, child) {
  for (var i = 0; i < parents.length; i++) {
    var node = child.parentNode;
    while (node !== null) {
      if (node === parents[i]) {
        return true;
      }
      node = node.parentNode;
    }
  }
  return false;
}

function eventCallback(e) {
  if (e.target && e.target.matches(this.options.selector)) {
    this.options.callback.call(this, e);
  } else if (isDescendant(this.parent.querySelectorAll(this.options.selector), e.target)) {
    this.options.callback.call(this, e);
  }
}

var MyEvent = {
  register: function register(options) {
    this.parent = document.querySelector(options.parentSelector);
    this.options = options;

    this.parent.addEventListener(options.event, eventCallback.bind(this), false);

    return this;
  },
  unregister: function unregister(options) {
    this.parent = document.querySelector(options.parentSelector);

    this.parent.removeEventListener(options.event, eventCallback, false);

    return this;
  }
};

myEvent = Object.create(MyEvent);

myEvent.register({
  event: 'click',
  parentSelector: '#parent',
  selector: '.item',
  callback: function(e) {
    alert('clicked!');
  }
});

myEvent.unregister({
  event: 'click',
  parentSelector: '#parent'
});

问题出在 bind(),它 returns 一个新函数。
来自文档

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

所以每次你调用bind你都会得到一个全新的函数,例如这里

this.parent.addEventListener(options.event, eventCallback.bind(this), false);

相同
var brandNewFunction = eventCallback.bind(this); // creates new function

this.parent.addEventListener(options.event, brandNewFunction, false);

所以你根本没有传递函数 eventCallback,你传递的是一个新函数,因此不能用

删除它
this.parent.removeEventListener(options.event, eventCallback, false);

因为您从未传入 eventCallback,并且 removeEventListener 的函数必须相同才能删除侦听器。
解决方案当然是这样调用

this.parent.addEventListener(options.event, eventCallback, false);

并找到其他一些巧妙的方法来传递您的选项等。