0

In a discussion at Passing 'this' and argument to addEventListener function without using bind, caching functions was mentioned.

For example, considering the following Event Listeners:

window.addEventListener('event1', callback1, false);
window.addEventListener('event2', callback2, false);
window.addEventListener('event3', callback3, false);
window.addEventListener('event4', callback4, false);
window.addEventListener('event5', callback5, false);

Can their removal be cached (for example in an array)?

var unloaders = []; // Keeps track of unloader functions
unloaders.push(window.removeEventListener('event1', callback1, false));
unloaders.push(window.removeEventListener('event2', callback2, false));
unloaders.push(window.removeEventListener('event3', callback3, false));
unloaders.push(window.removeEventListener('event4', callback4, false));
unloaders.push(window.removeEventListener('event5', callback5, false));

Finally, if they can be cached, how can they be executed at the correct time?

for (let i = 0, len = unloaders.length; i < len; i++) {
  //
}
4

1 回答 1

1

unloaders.push(window.removeEventListener('event1', callback1, false))不会把函数放到后面要执行的数组中,而是执行函数,把结果值放到数组中,即不是你想要的。

from the unloadother question实际上会构造一个匿名闭包函数并将其放入数组中,如此简化:

var unloaders = []; // Keeps track of unloader functions
unloaders.push(function() {
  window.removeEventListener('event2', callback2, false);
});

这有点类似于绑定函数并将绑定函数放入数组中,因此以下将产生相同的结果:

// This just binds the function, effectively creating a new function,
// but does not execute it (yet)
var bound = window.removeEventListener.bind(window, 'event2', callback2, false);
unloaders.push(bound);

我更喜欢第一种风格,但两者都可以,实际上没有闭包,但绑定函数可能会在某些情况下避免一些问题,因为闭包会关闭太多东西,使其人为地保持活力。但这通常很少发生。

无论如何,要最终调用存储在数组中的函数,您只需要遍历它,然后一个接一个地调用函数。

for (let i = 0, len = unloaders.length; i < len; i++) {
  unloaders[i]();
}

但是,为了避免异常提前退出循环,我建议您将调用包装在 try-catch 中。

for (let i = 0, len = unloaders.length; i < len; i++) {
  try {
    unloaders[i]();
  }
  catch (ex) {
    // Do something
  }
}

实际上,最好以相反的顺序(后进先出)调用卸载程序。

for (let i = unloaders.length - 1; i >= 0; i--) {
  try {
    unloaders[i]();
  }
  catch (ex) {
    // Do something
  }
}

另一个问题中的unload函数有更多的魔力:它返回一个函数,让您可以随时调用刚刚注册的卸载程序,并unloaders在这样做时将其从数组中正确删除。这对于unloadWindow我也提供的功能很重要。

于 2014-06-29T13:09:09.793 回答