如何为函数创建打开和关闭侦听器

时间:2020-05-15 03:47:24

标签: javascript events

我有一个函数,为简单起见,我有以下Pub / Sub模式:

Fiddle Demo

const Controller = function() {
  const listeners = {};

  this.on = (event, fn) => {
    listeners[event] = listeners[event] || [];
    listeners[event].push(fn);
  };

  this.off = (event, fn) => {
    if (listeners[event]) {
      for (var i = 0; i < listeners[event].length; i++) {
        if (listeners[event][i] === fn) {
          listeners[event].splice(i, 1);
          break;
        }
      }
    }
    console.log(listeners);
  };

  this.triggerListeners = (event, data) => {
    if (listeners[event]) {
      listeners[event].forEach((fn) => {
        fn(data);
      });
    }
  };
}

const ctl = new Controller();

ctl.on('click', () => console.log('foo'));

ctl.on('click', () => console.log('bar'));

document.querySelector('.trigger').addEventListener('click', () => {
	ctl.triggerListeners('click', 'some data');
})

document.querySelector('.remove').addEventListener('click', () => {
  ctl.off('click', () => console.log('bar'));
})
<button class="trigger">
Trigger Listeners
</button>

<button class="remove">
Click to remove listener
</button>

由于无法找到数组中的函数,我遇到了删除函数的问题,因为它们不是===

如果我单击按钮,我希望能够从列表中删除console.log('bar')功能。

1 个答案:

答案 0 :(得分:0)

正如我在上面的注释中提到的,您在.on()方法中传递的函数与您在.off()方法中传递的函数没有相同的引用

您可以尝试执行此操作,然后您会明白我的意思:

console.log(
  (() => console.log('log')) === (() => console.log('log'))
);

以上操作应返回false。

在JavaScript中,对象是引用类型。即使两个不同的对象具有相同的属性,它们也永远不会相等。仅将同一对象引用与其自身进行比较会得出true。

来源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Comparing_objects

在JavaScript中,函数是一类对象,因为它们可以像其他任何对象一样具有属性和方法。它们与其他对象的区别在于可以调用函数。简而言之,它们是函数对象。

来源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions

由于函数是引用类型,所以两个不同创建的函数不能相同。

要解决您的问题,则只需存储在.on()方法中传递的函数,并使用在.off()方法中传递的函数。

const ctl = new Controller();

const onBar = () => console.log('bar');

ctl.on('click', onBar);

ctl.off('click', onBar);

const Controller = function() {
  const listeners = {};

  this.on = (event, fn) => {
    listeners[event] = listeners[event] || [];
    listeners[event].push(fn);
  };

  this.off = (event, fn) => {
    if (listeners[event]) {
      for (var i = 0; i < listeners[event].length; i++) {
        if (listeners[event][i] === fn) {
          listeners[event].splice(i, 1);
          break;
        }
      }
    }
    console.log(listeners);
  };

  this.triggerListeners = (event, data) => {
    if (listeners[event]) {
      listeners[event].forEach((fn) => {
        fn(data);
      });
    }
  };
}

const ctl = new Controller();

const onBar = () => console.log('bar');

ctl.on('click', onBar);

ctl.off('click', onBar);