全域變數應該由有系統範圍相關性的物件保留,並且它們的命名應該避免含糊並儘量減少命名衝突的風險。在實踐中,這意味著你應該避免創建全局對象,除非它們是絕對必須的。
不過,恩,這些你早都知道了…
所以你對此是怎麼做的?傳統方法告訴我們,最好的消除全局策略是創建少數作為潛在模組和子系統的實際命名空間的全局物件。我將探索幾種有關命名空間的方式,並以我基於 James Edwards 最近的一篇文章所獲得的一個優雅、安全和靈活的解決方案結束。
靜態命名空間
我用靜態命名空間
作為那些命名空間標籤實際上硬編碼的解決方案的涵蓋性術語。是的,你可以將一個命名空間重新分配給另一個,不過新的命名空間將會引用和舊的那一個同樣的物件。
1.透過直接分配
最基礎的方法。這樣非常冗長,如果你還想重命名這些命名空間,你就有得活兒乾了。不過它是安全和清楚明白的。
var myApp = {} myApp.id = 0; myApp.next = function() { return myApp.id++; } myApp.reset = function() { myApp.id = 0; } window.console && console.log( myApp.next(), myApp.next(), myApp.reset(), myApp.next() ); //0, 1, undefined, 0
你也可以透過使用this
引用兄弟屬性來使將來的維護更輕鬆一些,不過這有一點冒險因為沒有什麼能阻止你的那些命名空間裡的方法被重新分配。
var myApp = {} myApp.id = 0; myApp.next = function() { return this.id++; } myApp.reset = function() { this.id = 0; } myApp.next(); //0 myApp.next(); //1 var getNextId = myApp.next; getNextId(); //NaN whoops!
2.使用物件字面量
現在我們只需要引用命名空間名一次,因此之後改變名字更簡單了一些(假設你還沒反覆引用這個命名空間)。仍有一個危險是this
的值可能會拋出一個『驚喜』 – 不過假設在一個物件字面結構裡定義的物件不會被重新分配相對安全一點。
var myApp = { id: 0, next: function() { return this.id++; }, reset: function() { this.id = 0; } } window.console && console.log( myApp.next(), myApp.next(), myApp.reset(), myApp.next() ) //0, 1, undefined, 0
3.模組模式
我發現自己最近用模組模式
更多。邏輯被一個方法包裝從全域域隔離開了(通常是自呼叫的),它傳回一個代表這個模組公開介面的物件。透過立即呼叫這個方法並分配結果給一個命名空間變量,我們就鎖住了這個命名變數中模組的 API。此外,任何沒有包含在傳回值中的變數將永遠保持私有,只對引用他們的公開方法可見。
var myApp = (function() { var id= 0; return { next: function() { return id++; }, reset: function() { id = 0; } }; })(); window.console && console.log( myApp.next(), myApp.next(), myApp.reset(), myApp.next() ) //0, 1, undefined, 0
如上物件字面量例子,命名空間名字可以輕易更換,不過還有額外優勢:物件字面量是四班的 – 它全是關於屬性分配,沒有支援邏輯的空間。此外,所有屬性必須被初始化,且屬性值無法輕易跨物件參考(因此,例如,內部閉包就不可能使用了)。模組模式沒有任何上述約束,並且給我們額外的隱私福利。
動態命名空間
我們也可以將這一節稱為命名空間注入
。命名空間由一個直接引用方法包裝內部
的代理代表 – 這意味著我們不再需要打包分配給命名空間的回傳值。這讓命名空間定義變得更靈活並且讓擁有多個存在於獨立命名空間中(或甚至在全局上下文中)的模組的獨立實例。動態命名空間支援模組模式的全部特徵並附加直覺和可讀性強的優勢。
4.提供命名空間參數
在這裡我們只是將命名空間作為參數傳給自呼叫方法。變數id
是私有的,因為他並沒有被指派給context
。
var myApp = {}; (function(context) { var id = 0; context.next = function() { return id++; }; context.reset = function() { id = 0; } })(myApp); window.console && console.log( myApp.next(), myApp.next(), myApp.reset(), myApp.next() ) //0, 1, undefined, 0
我們甚至可以把context
設定給全域物件(透過一個字的改變!)。這是庫主們的巨大財富– 他們可以將他們的特性包裝在一個自調用函數中,然後讓用戶來決定它們是不是全局的(John Resig 在他寫JQuery 時就是一個這個理論的早期採用者) 。
var myApp = {}; (function(context) { var id = 0; context.next = function() { return id++; }; context.reset = function() { id = 0; } })(this); window.console && console.log( next(), next(), reset(), next() ) //0, 1, undefined, 0
5.用this
作為命名空間代理
James Edwads 最近發布的一篇文章激起了我的興趣。 《My Favorite JavaScript Design Patter》 顯然被許多評論者誤解了,他們認為他也可能藉助於模組模式。這篇文章宣傳了多種技術(可能導致了讀者的迷惑),但是在它的核心部分是一點我已經修改並呈現為一個命名空間工具的很天才的東西。
這個模式的美就在於它只是按照這個語言被設計的方式使用 – 不多不少、不投機也不取巧。此外因為命名空間是透過this
關鍵字(它在給定的執行上下文中是不變的)注入的,它不可能被意外修改。
var myApp = {}; (function() { var id = 0; this.next = function() { return id++; }; this.reset = function() { id = 0; } }).apply(myApp); window.console && console.log( myApp.next(), myApp.next(), myApp.reset(), myApp.next() ); //0, 1, undefined, 0
更棒的是,apply
(以及call
) API 提供了與上下文和參數天然的隔離– 因此給模組創建者傳遞附加參數非常乾淨。下面的例子顯示了這一點,並且展示瞭如何獨立於多個命名空間來運行模組。
var subsys1 = {}, subsys2 = {}; var nextIdMod = function(startId) { var id = startId || 0; this.next = function() { return id++; }; this.reset = function() { id = 0; } }; nextIdMod.call(subsys1); nextIdMod.call(subsys2,1000); window.console && console.log( subsys1.next(), subsys1.next(), subsys2.next(), subsys1.reset(), subsys2.next(), subsys1.next() ) //0, 1, 1000, undefined, 1001, 0
當然如果我們如果我們如果我們需要一個全域 id 生成器,非常簡單…
nextIdMod(); window.console && console.log( next(), next(), reset(), next() ) //0, 1, undefined, 0
这个我们作为例子使用的 id 生成器工具并没有表现出这个模式的全部潜力。通过包裹一整个库和使用this
关键字作为命名空间的替身,我们使得用户在任何他们选择的上下文中运行这个库很轻松(包括全局上下文)。
//library code var protoQueryMooJo = function() { //everything } //user code var thirdParty = {}; protoQueryMooJo.apply(thirdParty);
其他的考虑
我希望避免命名空间嵌套。它们很难追踪(对人和电脑都是)并且它们会让你的代码因为一些乱七八糟的东西变得很多。如 Peter Michaux 指出的,深度嵌套的命名空间可能是那些视图重新创建他们熟悉和热爱的长包链的老派 Java 开发者的遗产。
通过 .js 文件来固定一个单独的命名空间也是可以的(虽然只能通过命名空间注入或者直接分配每一个变量),不过你应该对依赖谨慎些。此外将命名空间绑定到文件上可以帮助读者更轻易弄清整个代码。
因为 JavaScript 并没有正式的命名空间结构,所以有很多自然形成的方法。这个调查只详细说明了其中的一部分,可能有更好的技术我没有发现。我很乐意知道它们。
以上就是JavaScript 中的命名空间详细介绍的内容,更多相关内容请关注PHP中文网(www.php.cn)!

JavaScript核心數據類型在瀏覽器和Node.js中一致,但處理方式和額外類型有所不同。 1)全局對像在瀏覽器中為window,在Node.js中為global。 2)Node.js獨有Buffer對象,用於處理二進制數據。 3)性能和時間處理在兩者間也有差異,需根據環境調整代碼。

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

SublimeText3漢化版
中文版,非常好用

Dreamweaver Mac版
視覺化網頁開發工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!