javascript - 在不使用绑定(bind)的情况下将 'this' 和参数传递给 addEventListener 函数

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

removeEventListener in bootstrapped addon not working when addon disabled之后,我正在探索其他可能性。

除了使用 bind()并缓存绑定(bind)函数,有没有办法使用“this”并传递参数?

// works fine but can't pass argeement
contextMenu.addEventListener('popupshowing', 
     this.contextPopupShowing, false);

// passes the argument but 'this' is no longer available
contextMenu.addEventListener('popupshowing', 
    function(){this.contextPopupShowing(window);}, false);

我一直在使用许多事件监听器 bind()我正在寻找不使用 bind() 的替代方法

我什至试图捕获 window具有来自 <menupopup id="contentAreaContextMenu" ...> 的递归函数

更新: bind()干扰 removeEventListener

最佳答案

因为我们谈论的是无重启附加组件...许多无重启附加组件使用 unloadunloadWindow 辅助函数,以使其更容易实现 shutdown 并帮助处理诸如 addEventListener 之类的事情,所以请耐心等待。

助手 - unload

首先,unload 是一个辅助函数,您可以将另一个函数传递给该函数,它将在 shutdown 时运行(或者可以手动调用)。大多数实现都与此极为相似:

var unloaders = []; // Keeps track of unloader functions.

function unload(fn) {
  if (typeof(fn) != "function") {
    throw new Error("unloader is not a function");
  }
  unloaders.push(fn);
  return function() {
    try {
      fn();
    }
    catch (ex) {
      Cu.reportError("unloader threw " + fn.toSource());
      Cu.reportError(ex);
    }
    unloaders = unloaders.filter(function(c) { return c != fn; });
  };
}

然后您可以连接shutdown 来做正确的事情:

function shutdown() {
  ...
  for (let i = unloaders.length - 1; i >= 0; --i) {
    try {
      unloaders[i]();
    }
    catch (ex) {
      Cu.reportError("unloader threw on shutdown " + fn.toSource());
      Cu.reportError(ex);
    }
  }
  unloaders.length = 0;
}

使用卸载

现在您可以执行以下操作:

function startup() {
  setupSomething();
  unload(removeSomething);

  setupSomethingElse();
  var manualRemove = unload(removeSomethingElse);
  ...
  if (condition) {
    manualRemove();
  }
}

助手 - unloadWindow

您通常需要创建第二个函数 unloadWindow 以在您的附加组件关闭或窗口关闭时卸载内容,无论先发生什么。当窗口关闭时不删除东西可能非常棘手,并创建 Zombie compartments您的 bootstrap.js 和/或代码模块非常容易(这是来自编写和审查无重启附加组件的经验)。

function unloadWindow(window, fn) {
  let handler = unload(function() {
    window.removeEventListener('unload', handler, false);
    try {
      fn();
    }
    catch (ex) {
      Cu.reportError("window unloader threw " + fn.toSource());
      Cu.reportError(ex);
    }
  });
  window.addEventListener('unload', handler, false);
};

(有些人可能想“优化”这个,因为只有一个 “unload” 处理程序,但通常你只有这样的 unloadWindow 调用它不会'没关系。)

综合考虑

现在您可以.bind 东西并做任何事情并让卸载程序闭包跟踪它。此外,您可以使用它来将关闭代码放在初始化代码旁边,这可能会增加可读性。

function setupWindow(window, document) {
  var bound = this.contextPopupShowing.bind(this);
  contextMenu.addEventListener('popupshowing', bound, false);
  unloadWindow(window, function() {
    contextMenu.removeEventListener('popupshowing', bound, false);
  });

  // Or stuff like
  var element = document.createElement(...);
  contextMenu.appendChild(element);
  unloadWindow(window, function() {
    contextMenu.removeChild(element);
  });

  // Or just combine the above into a single unloader
  unloadWindow(window, function() {
    contextMenu.removeEventListener('popupshowing', bound, false);
    contextMenu.removeChild(element);
  });
}

关于javascript - 在不使用绑定(bind)的情况下将 'this' 和参数传递给 addEventListener 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24473309/

相关文章:

JavaScript block CSS

javascript - 如何将选择器和事件捕获从 jQuery 转换为纯 JS?

javascript - 选择一个选项后动态禁用下拉菜单

html - Firefox 中的 flexbox 溢出容器

Firefox 插件强调已知版本

firefox - 通过命令行或配置文件激活或停用插件

javascript - 从复选框表中获取值

php - 使用 PHP 的 jQuery 自动建议

javascript - Firefox 屏幕共享 MediaStreamTrack 到 Twilio

javascript - Firefox 无法识别编码!返回 "undefined"