2008-08-16 87 views
13

我經常遇到的網站,把所有的JavaScript的一個「命名空間」結構內沿有沒有一種「簡潔」的方式來在JavaScript中進行命名空間?

namespaces = { com : { example: { example.com's data} } 

但相對於其他命名空間框架的安全設置此功能似乎線路需要相對大幅金額代碼(定義爲> 2行)。我想知道是否有人知道一個簡潔的方法來做到這一點?以及是否有相對標準/一致的方式來構建它?例如。是直接連接到全局對象的「com」名稱空間還是通過名稱空間對象連接?

[編輯:哎呀,明顯{com = { ... } }不會完成任何接近我的意圖,感謝Shog9指出。 :D]

回答

19

Javascript沒有獨立的命名空間。它具有可以提供解析名稱範圍的函數和對給定範圍內可訪問的指定數據有貢獻的對象。

這裏是你的榜樣,糾正:

var namespaces = { com: { example: { /* example.com's data */ } } } 

這是一個變量namespaces被分配一個對象常量。該對象包含一個屬性:com,具有一個屬性的對象:example,這個對象大概會包含一些有趣的內容。

所以,你可以輸入類似namespaces.com.example。 somePropertyOrFunctionOnExample它會一切正常。當然,這也很荒謬。您沒有分層名稱空間,您的對象包含一個包含您實際關心的對象的對象。

var com_example_data = { /* example.com's data */ }; 

那的作品一樣好,沒有無謂的層次結構。

現在,如果你真的想建立一個層次,你可以嘗試這樣的事:

com_example = com_example || {}; 
com_example.flags = com_example.flags || { active: false, restricted: true}; 

com_example.ops = com_example.ops || (function() 
    { 
     var launchCodes = "38925491753824"; // hidden/private 
     return { 
     activate: function() { /* ... */ }, 
     destroyTheWorld: function() { /* ... */ } 
     }; 
    })(); 

......這是,恕我直言,相當簡潔。

+1

雖然,現在`com_example`將是全局對象的一部分。假設我們添加了更多的對象`com_something_else`,`com_etc`,那麼我們仍然在污染全局對象的根級別。如果我們在全局只有一個`com`對象,那麼所有其他對象都被添加了嗎?另外,我們不想覆蓋任何現有對象,如果使用多個庫,會發生什麼情況。 – Peter 2011-10-04 05:00:28

+2

@Peter:如果多個庫定義相同的符號,無論如何你都會遇到問題;這就是爲什麼像jQuery這樣的圖書館需要這麼長的時間才能將所有內容填充到單個全局對象中我的觀點並不是你應該使用多個頂層對象,而只是用深層嵌套的對象僞造名稱空間並不會真正爲你購買任何超過瘋狂對象名稱的東西。查看我最後一個更實用的方法示例:使用不太可能發生碰撞的單個全局名稱,然後使用允許不同位代碼向其中添加對象的技術。 – Shog9 2011-10-04 15:39:14

3

YUI library庫的代碼可以使用函數來處理命名空間,您可能會發現它更合適。其他圖書館也可以這樣做。

12

這是一篇由Peter Michaux撰寫的關於Javascript Namespacing的有趣文章。他討論了3種不同類型的Javascript命名空間的:

  1. 前綴命名空間
  2. 單一對象命名空間
  3. 嵌套對象命名空間

我不會抄襲了他在這裏說,但我認爲他的文章是非常翔實。

彼得甚至指出,其中一些人有性能方面的考慮。我認爲這個話題很有意思,因爲考慮到新的ECMAScript Harmony計劃已經放棄了命名空間和包裝的4.0計劃。

6

我試圖按照雅虎的慣例在全球範圍內製作單個父對象來包含所有內容;

var FP = {}; 
FP.module = {}; 
FP.module.property = 'foo'; 
1

作爲替代點或下劃線,你可以使用美元符號:

var namespaces$com$example = "data"; 
5

爲了確保不覆蓋現有對象,你要那麼是這樣的:

if(!window.NameSpace) { 
    NameSpace = {}; 
} 

var NameSpace = window.NameSpace || {}; 

通過這種方式,您可以將它放在應用程序/網站中每個文件的頂部,而不用擔心覆蓋命名空間對象。此外,這將使您能夠爲每個文件單獨編寫單元測試。

1

我想也是這個(source):

(function() { 
    var a = 'Invisible outside of anonymous function'; 
    function invisibleOutside() { 
    } 

    function visibleOutside() { 
    } 
    window.visibleOutside = visibleOutside; 

    var html = '--INSIDE Anonymous--'; 
    html += '<br/> typeof invisibleOutside: ' + typeof invisibleOutside; 
    html += '<br/> typeof visibleOutside: ' + typeof visibleOutside; 
    contentDiv.innerHTML = html + '<br/><br/>'; 
})(); 

var html = '--OUTSIDE Anonymous--'; 
html += '<br/> typeof invisibleOutside: ' + typeof invisibleOutside; 
html += '<br/> typeof visibleOutside: ' + typeof visibleOutside; 
contentDiv.innerHTML += html + '<br/>';​ 
0

使用對象文本,要麼在this對象或明確的名稱做命名空間基礎上,包含了函數的局部變量的兄弟性能。例如:

var foo = { bar: function(){return this.name; }, name: "rodimus" } 
 
var baz = { bar: function(){return this.name; }, name: "optimus" } 
 

 
console.log(foo.bar()); 
 
console.log(baz.bar());

或不明確的name屬性:

var foo = { bar: function rodimus(){return this; } } 
 
var baz = { bar: function optimus(){return this; } } 
 

 
console.log(foo.bar.name); 
 
console.log(baz.bar.name);

使用或不使用this

var foo = { bar: function rodimus(){return rodimus; } } 
 
var baz = { bar: function optimus(){return optimus; } } 
 

 
console.log(foo.bar.name); 
 
console.log(baz.bar.name);

使用RegExpObject構造函數添加名稱的屬性來對抗變量和其他共同的名字,然後用hasOwnProperty測試做檢查:

var foo = RegExp(/bar/); 
 
    
 
/* Add property */ 
 
foo.name = "alpha"; 
 

 
document.body.innerHTML = String("<pre>" + ["name", "value", "namespace"] + "</pre>").replace(/,/g, "&#09;"); 
 

 
/* Check type */ 
 
if (foo.hasOwnProperty("name")) 
 
    { 
 
    document.body.innerHTML += String("<pre>" + ["foo", String(foo.exec(foo)), foo.name] + "</pre>").replace(/,/g, "&#09;"); 
 
    } 
 

 
/* Fallback to atomic value */ 
 
else 
 
    { 
 
    foo = "baz"; 
 
    } 
 

 
var counter = Object(1); 
 

 
/* Add property */ 
 
counter.name = "beta"; 
 

 
if (counter.hasOwnProperty("name")) 
 
    { 
 
    document.body.innerHTML += String("<pre>" + ["counter", Number(counter), counter.name] + "</pre>").replace(/,/g, "&#09;"); 
 
    } 
 
else 
 
    { 
 
    /* Fallback to atomic value */ 
 
    counter = 0; 
 
    }

DOM使用以下約定來命名空間HTML和SVG元素接口定義:

  • HTMLTitleElement
  • SVGTitleElement
  • SVGScriptElement
  • HTMLScriptElement

JavaScript的核心採用原型來命名空間中的toString方法多態性的簡單形式。

參考

相關問題