6

在为 Firefox 开发扩展时,我一直在阅读有关全局命名空间污染的信息,并且我想在我的扩展中尽可能地避免它。有几种解决方案,但通常,这些解决方案似乎只围绕为您的扩展声明一个全局变量,并将所有内容放入其中。因此,您只需向全局命名空间添加一个额外的变量,这还不错。

顺便说一句,我已经向我提出了一个解决方案,可以避免将任何额外的变量放入全局命名空间;将所有内容包装在一个函数中。这里的问题是在您的 XUL 覆盖中没有任何可参考的内容。您必须在叠加层中声明元素,然后在 JS 中添加大量s 来替换XUL 中addEventListener类似的东西。oncommand="..."我不想这样做;我绝对希望我的 XUL 在 XUL 本身中包含事件,因为我认为它看起来更干净,所以这不是我的解决方案。因此,我需要至少 1 个全局变量oncommand="..."来引用 XUL 属性。

因此,共识似乎是为您的扩展提供一个(也是唯一一个)变量,并将所有代码放入其中。这就是问题所在:通常,人们建议将该变量命名为一个漂亮的长而独特的名称,以便与其他变量发生冲突的可能性几乎为零。因此,如果我的扩展 ID 是myextension@mycompany.com,我可以将变量命名为myextensionAtMycompanyDotCom,或com.mycompany.myextension. 这有利于避免全局命名空间中的冲突,但有一个问题;该变量名又长又笨重。我的 XUL 将到处都是对事件处理程序的引用,如下所示oncommand="myextensionAtMycompanyDotCom.doSomeEvent". 没有办法避免在我的 XUL 覆盖中引用全局命名空间,因为覆盖只是被添加到浏览器窗口的 DOM 中;它没有自己的命名空间,所以我们不能以某种方式将扩展的变量范围限制在我们自己的覆盖范围内。所以,在我看来,有四种解决方案:

1.在XUL中使用长变量名即可

这会导致相当笨拙、冗长的 XUL 代码,例如:

<statusbarpanel id="myStatusBar" onmousedown="myextensionAtMycompanyDotCom.onMyStatusBarClick();">

2.给短变量名添加随机元素

我们为我们的扩展提供了一个更好的短变量名,比如说myExt,并添加一些随机字符以使其几乎可以肯定是唯一的,例如myExtAX8T9. 然后在 XUL 中,我们有:

<statusbarpanel id="myStatusBar" onmousedown="myExtAX8T9.onMyStatusBarClick();">

显然,这会导致代码相当丑陋甚至令人困惑,因为随机字符看起来很奇怪,并使其看起来像某种临时变量。

3. 根本不声明任何全局变量

您可以将所有内容都包含在函数中。当然,这意味着在您的 XUL 中没有可引用的内容,因此每个事件都必须附加到addEventListener您的 JavaScript 代码中使用的 XUL 元素。我不喜欢这个解决方案,因为如上所述,我认为在 XUL 代码中引用事件比搜索大量 JS 代码来查找哪些事件附加到哪些 XUL 元素更简洁。

4. 只需在 XUL 中使用短变量名

我可以只调用我的扩展的变量myExt,然后我会得到很好的 XUL 代码,例如:

<statusbarpanel id="myStatusBar" onmousedown="myExt.onMyStatusBarClick();">

当然,这个短名称更有可能与全局命名空间中的其他内容发生冲突,因此并不理想。

那么,我错过了什么吗?我上面提出的 4 种解决方案有什么替代方案吗?如果不是,那么 4 个中最好的是什么(鉴于 #3 对我来说基本上是不可接受的),为什么?

4

2 回答 2

5

我们使用这篇博文中描述的 JavaScript 模块模式:http: //www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth。您可以按照所述导出要在 XUL 处理程序中使用的符号。

另外,我们使用一个颠倒的主机名作为模块名前缀,以确保我们控制命名空间:

/* Set up the global namespace. */
if (typeof(com) == "undefined") var com = {};
if (!com.salsitasoft) com.salsitasoft = {};

/* Main namespace. */
com.salsitasoft.myExtensionGlobalStuffGoesHere = (function (my) {
  return my;
})(com.salsitasoft.myExtensionGlobalStuffGoesHere || {});

更新:如果它已经存在,我将其更改为将 com.salsitasoft.myExtensionGlobalStuffGoesHere 传递到闭包中,以便命名空间可以分布在多个文件中。

于 2011-07-13T10:17:22.903 回答
1

无论哪种方式,您的函数都必须“存在”于某个地方,因此您无法避免声明某种命名空间。我也同意您的观点,即在 XUL 中定义事件比附加它们更好。因此,我提出了 3+4 之间的混合:

  • 为您的插件找到一个独特但尽可能吸引人的命名空间,例如“catchyseo”。
  • 将插件的所有代码和所有变量放在此命名空间中。使用匿名函数包装器模式,例如(查看一些 jQuery 插件作为代码示例):

    window.catchyseo = (function(){var private = x; [...] })();
    
  • 在您的命名空间中,公开一些您可以在 XUL 中引用的事件处理程序。

这种方法为您提供了两全其美:您可以在 XUL 中定义您的事件,并且您有一个没有任何全局名称空间污染的封闭名称空间 - 除了您的一个名称空间变量。

于 2011-07-13T10:01:53.810 回答