我有一个函数,为简单起见,我有以下Pub / Sub模式:
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')
功能。
答案 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);