下面这些代码是browserOverlay.js文件的内容,这个脚本文件会在一个界面文件(browserOverlay.xul)中被引用。
// 扩展对应的唯一全局变量 var myExtension = {}; (function() { // 注册命名空间 var namespaces = []; this.ns = function(fn) { var ns = {}; namespaces.push(fn, ns); return ns; };
// 初始化 this.initialize = function() { for (var i = 0; i < namespaces.length; i += 2) { var fn = namespaces[i]; var ns = namespaces[i + 1]; fn.apply(ns); } };
// 收尾的清理工作 this.shutdown = function() { window.removeEventListener("load", myExtension.initialize, false); window.removeEventListener("unload", myExtension.shutdown, false); };
// 注册两个事件处理程序,维护扩展的生存期 window.addEventListener("load", myExtension.initialize, false); window.addEventListener("unload", myExtension.shutdown, false); }).apply(myExtension);
正如我前文所述,这里只有一个全局对象myExtension。
总结一下,这个对象要实现下面几个方法:
- ns - 注册一个新的命名空间。
- initialize - 初始化所有的命名空间。
- shutdown - 收尾的清理工作。
当然这段代码也会确保initialize和shutdown方法会在正确的时间被调用,这也是两个事件处理程序的作用。
browserOverlay.xul现在看起来可能会是下面这个样子:
<?xml version="1.0"?> <overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/ there.is.only.xul"> <script src="chrome://namespace/content/browserOverlay.js" type="application/x-javascript"/> <script src="chrome://namespace/content/Module1.js" type="application/x-javascript"/> <script src="chrome://namespace/content/Module2.js" type="application/x-javascript"/> </overlay>
在这里,Module1.js和Module2.js两个文件是一模一样的。
myExtension.ns(function() { // TODO: 脚本内的全部代码 });
在不同的模块间共享数据
我们已经把所有的脚本置于本地的作用域下,现在让我们来回答上面提到的第二个问题,就是在不同的命名空间下如何共享函数和数据。基本的思路当然是要利用我们唯一的全局对象啦,也就是myExtension。
首先,让我们先来看看下面这段代码(都在lib.js文件中)
myExtension.LIB = { // 共享函数接口 getCurrentURI: function() { return window.location.href; },
// 扩展对象的快捷方式 theApp: myExtension,
// XPCOM组件的快捷方式 Cc: Components.classes, Ci: Components.interfaces,
// 等等。。。 };
你可以注意到,这段代码在全局的myExtension对象下建立了一个新的LIB属性,这个属性定义了一个函数库,是要在扩展所有的模块中共享的。你应该在Java的包结构中看到过相同的做法,所有的命名空间呈树状结构分布在一个唯一的对象下面,YUI也是这样子做的。
lib.js文件也在browserOverlay.xul中引入,紧随browserOverlay.js的后面。
<?xml version="1.0"?> <overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/ there.is.only.xul"> <script src="chrome://myextension/content/browserOverlay.js" type="application/x-javascript"/> <script src="chrome://myextension/content/lib.js" type="application/x-javascript"/> <script src="chrome://myextension/content/Module1.js" type="application/x-javascript"/> <script src="chrome://myextension/content/Module2.js" type="application/x-javascript"/> </overlay>
让我们对模块内的脚本也做一些改进。
myExtension.ns(function() { with(myExtension.LIB) { // TODO: 脚本内的全部代码 var moduleVariable = "Accessible only from withing this module"; dump("myExtension.Module initialization " + getCurrentURI() + "\n"); } });
通过利用with语句,我们可以方便的访问所有的库函数,就像访问全局变量一样。
既然我们要访问全局对象,还可以像下面这样利用theApp这个快捷方式(尤其是命名空间名字太长的时候)
myExtension.ns(function() { with(myExtension.LIB) { // TODO: 脚本内的全部代码 theApp.sharedValue = "A new shared property"; } });
下面这个图是从UML的角度来纵观整个架构。

大家可以在 这里 下载本文提到的演示扩展。
本文链接:http://www.blueidea.com/tech/web/2009/6452.asp
出处:七月佑安
责任编辑:bluehearts
上一页 Firefox扩展的全局命名空间污染 [1] 下一页
◎进入论坛网页制作、WEB标准化版块参加讨论,我还想发表评论。
|