亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

JS應用在Firebug中的擴展架構模式

2024-09-06 12:40:55
字體:
來源:轉載
供稿:網友

全局變量是魔鬼,這句話在javascript存在的地方應該就是成立的,當然firefox擴展也不例外,如果大家把多于一個的對象置于全局命名空間下,和其他擴展的沖突是很容易發生的,而且發現這種沖突引起的錯誤是很困難的,因為每個人的擴展列表都不一樣啊。避免全局名字污染已經成了一個基本原則,本文從這點引申,介紹了一個應用在firebug中的擴展架構模式,非常值得推薦。

【原文】firefox extensions: global namespace pollution
【作者】jan odvarko
【譯文】http://cuimingda.com/2009/01/
【譯者】明達

以下是對原文的翻譯

最近有幾個開發者向我咨詢如何設計firefox擴展的架構,第一個顯現在我腦海中的答案就是要合理定義那些在chromewindow作用域下的全局變量。

不合理的定義全局變量,可以輕易的引發不同擴展之間的沖突,而這些完全是應該避免的(這也是amo審閱的步驟之一),因為沖突所引發的問題是很難被發現的。就目前的開發環境來說,全局變量就是魔鬼,尤其是采用oop開發模式的時候。

我不想重復介紹如何從頭開始開發一個firefox擴展,對于這方面已經有很多非常詳細的文章。本文的重點放在如何設計一個更加易于維護的firefox擴展架構。

如果你對前面的介紹感興趣,那就接著看吧。。。

命名空間架構

擴展之間發生沖突的重要原因就是因為定義了不合理的全局變量。我認為對每個擴展來說,只有一個全局變量已經很足夠了(可以根據擴展的信息來定義這個唯一的全局變量的名字,比如可以是擴展的名字、域名、地址等),不僅可以滿足我們的開發,而且可以避免那些令人討厭的沖突。

firebug使用的命名空間架構,基本建立在著名的module pattern基礎上(這種模式最早由douglas crockfod定義)下的。這種模式簡單而清晰,但其實我在很長時間里都不是很明確這種模式究竟是如何工作的(i hadn’t understand how it actually works for a long time)。我相信每個開發者都可以充分利用這個方法。

基本的思路是將每個javascript腳本文件放進自己的作用域,這是通過一個函數來實現的,沒有定義任何全局變量,比如下面這段代碼:

function() {
  // todo: 腳本文件中的全部代碼
}

我管這個函數就叫做命名空間。擺在眼前的第一個問題是,如何確定這個函數的內容會在正確的時間被調用。第二個問題是,如何在多個腳本文件中共享對象(這個會在后面的章節解答)。 firebug通過將所有的命名空間進行注冊,并在firefox chrome ui加載的時候調用來解決第一個問題,也就是下面這段代碼:

myextension.ns(function()
{
  // todo: 腳本文件中的全部代碼
});

命名空間(就是原來定義的那個函數)為當作myextension.ns函數的一個參數,而myextension對象是這個擴展中定義的唯一全局變量。這個對象代表著整個擴展。不用擔心這個名字太長,我們可以為他建立個快捷方式(在實際開發中,這個名字可能會類似 comsoftwareishardmyextension這個樣子)。

ns函數比較簡單,就是把所有的方法都添加到一個數組中。

var namespaces = [];
this.ns = function(fn)
{
  var ns = {};
  namespaces.push(fn, ns);
  return ns;
};

執行已注冊命名空間的函數,不可以命名為apply,別的什么名字都可以。

this.initialize = function() {
  for (var i = 0; i < namespaces.length; i += 2) {
      var fn = namespaces[i];
      var ns = namespaces[i + 1];
      fn.apply(ns);
  }};

現在,然我們把前面的代碼連起來,看看全局擴展對象是如何定義和初始化的。

|||

下面這些代碼是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: 腳本內的全部代碼
});

在不同的模塊間共享數據

我們已經把所有的腳本置于本地的作用域下,現在讓我們來回答上面提到的第二個問題,就是在不同的命名空間下如何共享函數和數據?;镜乃悸樊斎皇且梦覀兾ㄒ坏娜謱ο罄玻簿褪莔yextension。

首先,讓我們先來看看下面這段代碼(都在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的角度來縱觀整個架構。

大家可以在 這里 下載本文提到的演示擴展。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美激情国产日韩精品一区18| 精品国产户外野外| 欧美日韩在线视频一区二区| 久久久久久久久久国产| 亚洲精品免费一区二区三区| 亚洲天堂av图片| 中文字幕亚洲精品| 日韩欧美一区二区三区久久| 久久天天躁狠狠躁夜夜躁| 深夜福利一区二区| 人九九综合九九宗合| 亚洲精品中文字| 国产精品美女视频网站| 精品在线小视频| 一区二区三区 在线观看视| 欧美性猛交xxxx偷拍洗澡| 久久不射热爱视频精品| 亚洲天堂男人天堂女人天堂| 日韩国产激情在线| 国产日韩换脸av一区在线观看| 国产有码在线一区二区视频| 亚洲成人在线网| 国产精品丝袜久久久久久不卡| 亚洲图中文字幕| 亚洲成人精品在线| 日本一欧美一欧美一亚洲视频| 久久视频在线播放| 91精品国产91久久久久久吃药| 丝袜一区二区三区| 日本精品久久久久影院| 日韩成人av一区| 久久综合电影一区| 欧美日韩成人在线播放| 日本伊人精品一区二区三区介绍| 亚洲国产成人精品久久久国产成人一区| 亚洲天堂久久av| 欧美电影在线观看高清| 欧美一级大片视频| 亚洲天堂男人天堂女人天堂| 亚洲成人激情视频| 红桃视频成人在线观看| 国产极品精品在线观看| 欧美肥婆姓交大片| 精品视频9999| 日韩av电影在线网| 成人免费网站在线观看| 欧美电影在线观看完整版| 久久精品国产成人| 不卡av在线播放| 欧美成人精品h版在线观看| 国产精品久久久久久超碰| 91精品国产沙发| 538国产精品一区二区在线| 色老头一区二区三区在线观看| 永久免费看mv网站入口亚洲| 日韩av免费观影| 狠狠爱在线视频一区| 中文字幕亚洲无线码a| 中文字幕日韩av综合精品| 国产精品678| 国产精品丝袜视频| 亚洲性猛交xxxxwww| 51精品国产黑色丝袜高跟鞋| 91国在线精品国内播放| 亚洲一区二区福利| 色婷婷综合久久久久| 欧美丝袜一区二区三区| 黑人狂躁日本妞一区二区三区| 懂色av影视一区二区三区| 欧美www在线| 欧美中文在线观看国产| 亚洲石原莉奈一区二区在线观看| 日韩av综合中文字幕| 亚洲女性裸体视频| 亚洲午夜精品久久久久久性色| 欧美中文在线观看国产| 午夜精品久久久久久久久久久久久| 精品亚洲aⅴ在线观看| 久久99热精品这里久久精品| 国产精品丝袜高跟| 国产精品99一区| 国产欧美最新羞羞视频在线观看| 国产精品老女人精品视频| 国产精品一区二区久久精品| 黑人精品xxx一区| 欧美肥老妇视频| 日韩视频欧美视频| 亚洲激情视频网站| 国产精品亚洲аv天堂网| 久久人人爽人人爽人人片av高清| 欧美一级淫片videoshd| 欧美日韩国产在线看| 日韩中文字幕免费| 欧美在线视频播放| 中文字幕亚洲综合| 最新69国产成人精品视频免费| 欧美国产中文字幕| 国产精品对白刺激| 26uuu亚洲国产精品| 久久91超碰青草是什么| 欧美一区二粉嫩精品国产一线天| 成人免费淫片aa视频免费| 欧美精品国产精品日韩精品| 中文字幕av一区二区| 亚洲国产古装精品网站| 成人妇女免费播放久久久| 久久久久久久亚洲精品| 奇门遁甲1982国语版免费观看高清| 美女999久久久精品视频| 久久久久久久久国产| 狠狠躁天天躁日日躁欧美| 欧美性猛交xxxx乱大交| 久久久久久久国产精品视频| 视频直播国产精品| 国产精品久久久久久久久久三级| 国产成人短视频| 久久久久在线观看| 久久久久久亚洲| 91av在线播放| 91精品国产自产91精品| 久久久精品久久久久| 色妞色视频一区二区三区四区| 色噜噜狠狠狠综合曰曰曰| 成人免费福利视频| 精品久久在线播放| 91久久综合亚洲鲁鲁五月天| 亚洲第一男人av| 亚洲精品一区在线观看香蕉| 亚洲欧美国产高清va在线播| 久久精品成人欧美大片古装| 欧美极品第一页| 亚洲精品成人久久电影| 久久九九全国免费精品观看| 欧美国产日韩视频| 668精品在线视频| 欧美日韩在线免费观看| 性色av一区二区三区免费| 久热精品视频在线观看| 国产精品极品在线| 久久久噜久噜久久综合| 亚洲色图日韩av| 狠狠干狠狠久久| 一本一道久久a久久精品逆3p| 成人黄色片网站| 激情久久av一区av二区av三区| 欧美色欧美亚洲高清在线视频| 欧美另类69精品久久久久9999| 欧美日韩精品中文字幕| 欧美国产精品va在线观看| 久久久精品视频在线观看| 欧美激情国产日韩精品一区18| 欧美做受高潮电影o| 亚洲精品成人免费| 欧美电影电视剧在线观看| 国产亚洲精品久久久优势| 一区二区国产精品视频| 欧美性猛交xxxx黑人| 国产婷婷成人久久av免费高清| 亚洲乱码一区av黑人高潮| 精品五月天久久| 成人伊人精品色xxxx视频| 精品视频在线观看日韩| 亚洲美女精品成人在线视频| 69影院欧美专区视频|