JavaScript:命名空间污染

3
我正在尝试将我的插件提交到Mozilla网站,但是我遇到了这个烦人的警告: enter image description here 代码(在mf_options.js中)非常简单(我认为问题只存在于“start storage”和“end storage”之间):
// start Storage
var url = "http://mafiaafire.com";
var ios = Components.classes["@mozilla.org/network/io-service;1"]
          .getService(Components.interfaces.nsIIOService);
var ssm = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
          .getService(Components.interfaces.nsIScriptSecurityManager);
var dsm = Components.classes["@mozilla.org/dom/storagemanager;1"]
          .getService(Components.interfaces.nsIDOMStorageManager);
var uri = ios.newURI(url, "", null);
var principal = ssm.getCodebasePrincipal(uri);
var storage = dsm.getLocalStorageForPrincipal(principal, "");
// end Storage



function display_blocked_list1() {

  var list = storage.getItem('domain_list_original');
  if (list !== undefined) {

    var strSingleLineText = list.replace(new RegExp( " ", "g" ),    "<br>"  );

    var status = document.getElementById("div1");
 status.innerHTML = strSingleLineText;
   }

  var list2 = storage.getItem('domain_list_redirect');
  if (list2 !== undefined) {

    // Strip out all line breaks.
    var strSingleLineText2 = list2.replace(new RegExp( " ", "g" ),  "<br>"  );

    var status2 = document.getElementById("div2");
 status2.innerHTML = strSingleLineText2;
   }


  var list3 = storage.getItem('list_expiry_date');

  if (list3 !== undefined) {



var dateArray = list3.split(",");
var future_date = new Date(dateArray[0],dateArray[1],dateArray[2]);
future_date.setDate(future_date.getDate()+2);

    var status2 = document.getElementById("div3");
 status2.innerHTML = future_date;

  }
// ##################################################

}

3
或许这个建议有些愚蠢,但你是否点击了那个链接? - Blender
我试过了,但这对我来说有点太高级的 JavaScript 了 :( 我习惯了旧的简单方式,正在学习新的东西。 - Ryan
1
只需将您的代码放入(function() { /* code here */ })();即可。 - Raynos
好的,我已经做了,但是当我尝试像这样调用它时<body onLoad="display_blocked_list1()">,我会收到一个错误。 - Ryan
请注意,对于加载到您自己的窗口中的脚本,可以安全地忽略此警告。但是,当您的脚本加载到浏览器窗口或其他常见窗口(通常通过叠加层)时,任何全局变量都应具有唯一的名称 - 否则,其他扩展程序可能会选择使用相同的名称用于其变量,这将会造成混乱。 - Wladimir Palant
3个回答

3

您一定要查看这个链接。然而,我也收到了这条消息,我相当确定我的代码不包含任何(污染)全局变量。

但是如果这确实是您使用的代码,那么您声明的任何函数和变量都将是全局的。最简单的情况是,在匿名函数调用中包装代码:

(function() {
    // your code here
}());

如果您需要一个全局变量,因为您必须从XUL元素调用函数,请确保只有一个。在上面的函数调用中创建它。
window.YourPluginNamespace = {
    // all functions or "subspaces" here
};

但是这不是来自于我的主JS文件... 这来自于一个次要的JS文件,它只有一些辅助函数,与作为插件的主要JS文件没有真正的关联。 - Ryan

2

将你的代码放在一个函数包装器中,这样你的var变量就只在该函数体内是局部的,如果需要让某些内容成为全局变量,就要明确地将它们附加到全局对象上。

(function (global) {

  // your code here

  global.myGlobalVar = myVar

}(this));

我在8个不同的文件中遇到了上述错误,请您对上述文件进行更改,然后我会根据您所做的更改来处理其他文件,可以吗? - Ryan
@Ryan,不,我没有访问你的源代码的权限,也不应该有。如果你有多个源文件,则应考虑使用压缩器将它们合并为一个文件。Closure编译器具有输出包装器选项,你可以使用它来在编译后的输出周围添加封套。 - Mike Samuel
是的,它是www.ezee.se/tests/testing.js。 - Ryan
我尝试了你写的内容,但是我该如何在我目前正在进行的html页面中调用它:<body onLoad="display_blocked_list1()">。 - Ryan
1
@Ryan,你需要将 display_blocked_list1 导出为全局变量,可以像上面这样做:global.display_blocked_list1 = display_blocked_list1; - Mike Samuel
显示剩余2条评论

0
问题在于您使用了太多全局变量,即在函数外定义的变量。
想象一下这种情况:我的插件Foo使用了一个名为sheep的变量。
var sheep = 10;

你的插件Bar使用了一个同名变量sheep:

var sheep = 20;

当我尝试访问sheep时,如何确保您的插件没有修改它?这也是插件使用匿名函数foo = function() {的原因,因为它们是本地的。
为了使全局变量更本地化,请将整个脚本包装在一个匿名函数中:
(function() {
  var sheep = 10;
}());

现在,您可以随心所欲地处理sheep,并且它将是本地的。请注意,如果您计划使应用程序更复杂,则需要更好的支撑结构。这种方法不完全是防弹或可扩展的...

如果这不是防弹或可扩展的,为什么要使用它? - Ryan
它并不是完全防弹的,但只要子弹不太高规格,它就有一点防弹性。也就是说,对于大多数目的来说足够好了。请注意Felix King的答案,了解如何使匿名函数内部的功能在页面其他地方可用(例如,在您的onload中)。 - nnnnnn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接