缓存Array中的函数

时间:2014-06-29 12:51:08

标签: javascript firefox firefox-addon firefox-addon-restartless

Passing 'this' and argument to addEventListener function without using bind的讨论中,提到了缓存功能。

例如,考虑以下事件监听器:

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);

是否可以缓存它们的删除(例如在数组中)?

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));

最后,如果可以缓存它们,它们如何在正确的时间执行?

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

1 个答案:

答案 0 :(得分:1)

unloaders.push(window.removeEventListener('event1', callback1, false))不会将函数放在数组中以便稍后执行,而是执行函数并将结果值放入数组中,即不是你想要的。

来自另一个问题的unload实际上会构造一个匿名闭包函数并将其放入数组中,因此简化了:

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函数中还有一些 magic :它返回一个函数,让您可以随时调用刚刚注册的卸载程序,并将其从这样做时unloaders数组。这对我也提供的unloadWindow函数很重要。