現代Web
前端的特征之一是由不止一個庫所組成的,或者沒有達到稱為“庫”的标準,有可能就是僅僅若幹個小部件(Widget)
、某一段的JavaScript
代碼(Snippets)
所組成。從開發者的角度而言,你所産生的代碼有很大的機會與其他的代碼産生沖突,因為我們清楚JavaScript
是一門格外自由的語言,允許全局變量星羅棋布地存在,這樣的話太多就極容易造成污染。是以有必要采用一定措施降低這種沖突發生的可能性。
extjs.com
的官方論壇它目前采用了來自三方面的程式(如上
圖一
):
Ext
精減版(ext.js)
流量分析(urchin.js)
論壇自帶的vRulletin
腳本(vbulletin_*.js)
如果有新需求,還可能加入其他第三方的JavaScript
庫。進入Firebug
的Dom
頁籤觀察,位于window
對象下面存放的變量數以百計,這些變量正是Ajax
庫所帶來到JavaScript
頂層全局環境的。JavaScript
是一門帶有變量作用域的語言,任何一個變量若不加var
則可表示為一個全局成員,就加入在window
對象(即全局空間)下。
庫并沒有使用太多的全局變量在裡面。任何一個它的類均安排在“Ext
”
對象底下,是以說整個架構隻使用了一個全局變量Ext
(如下
圖)。
命名空間(Namespace)
表示辨別符(Identifier)
的上下文(Context)
。一個辨別符可在多個命名空間中定義,它在不同命名空間中的含義是互不相幹的。這樣,在一個新的命名空間中可定義任何辨別符,它們不會與任何已有的辨別符發生沖突,因為已有的定義都處于其他命名空間中。把實作的代碼安排在一個特定的命名空間中,由各個類或單例構成,這樣的JavaScript
編碼風格不僅有良好的組織,直覺可維護的優點,而且還能有避免它方代碼幹擾、竄改的好處。“為變量建立其命名空間,這樣類就有了“安身之所”,不是飄蕩四處的“全局變量。”(摘自API
文檔)”。
提示: 筆者有一次就 API 翻譯的問題與參與人員發生小誤會,有兩份檔案都是 DataField.js ,分别在不同的包中,一個是 /widget/DataField.js ;另外一個是 /widget/form/DataField.js 。但筆者誤認為“未翻譯的”當作“已翻譯的”,這樣大家碰頭時就發生誤會了。看來還真是命名空間相沖突而導緻的結果,最後大家認真溝通下才把問題解釋清楚。
使用Ext.ns()
可以實作簡單的命名空間聲明方式,其全稱是Ext.namespace()
。Ext.ns()
用法如下
所示:
/* Ext.namespace會建立下列對象,若不存在的話 */
Ext.namespace('App', 'App.panel', 'App.data');
/* // 等價于注釋的語句
if (!App)
App = {};
if (!App.form)
App.form = {};
if (!App.data)
App.data = {};
*/
/* 定義App.form包内部的新類SamplePanel */
App.panel.SamplePanel = Ext.extend(Ext.Panel, {
initComponent: function(){
/*component configuration code here! */
App.form.SamplePanel.superclass.call(this);
}
});
Ext.namespace()
傳入的參數中不能包含
ECMAScript
關鍵字,例如“
com.extjs.long
中的
long
是關鍵字,不能被
ns
方法執行。
方法的關鍵地方之一是利用了eval
函數解析字元串為對象,若在一些不支援eval()
函數環境(如Adobe
AIR
的安全沙箱下),可參考YUI
庫的namespace()
方法,主要原理是JavaScript
的對象“索引式”聲明增加Hash
表内元素,缺點是有第一個因子項的限制,因為該方法中須明确命名空間的第一個因子項。
// Yahoo! UI namespce方法源碼
namespace = function() {
YAHOO = {}; // YAHOO是全局變量
var a=arguments, o = null, i, j, d;
// 周遊所傳入的參數。JavaScript的參數具有參數個數不确定性
for (i=0; i<a.length; i=i+1) {
d = a[i].split(".");// 傳回數組,每個字元串以.分割開後,成為數組的元素
o = YAHOO;
// 規定所有的命名空間均以YAHOO開頭,如果依據顯式聲明則忽略
for (j=(d[0] == "YAHOO") ? 1 : 0; j<d.length; j=j+1) {
o[d[j]]=o[d[j]] || {}; // 跳過目前已經存在的對象
o=o[d[j]]; // 移位到數組的下一個元素
}
}
return o;
}
一書(覆寫包含2.2/3.03的版本)的全面介紹。