JavaScript 中的命名空間詳細介紹
全域變數應該由有系統範圍相關性的物件保留,並且它們的命名應該避免含糊並儘量減少命名衝突的風險。在實踐中,這意味著你應該避免創建全局對象,除非它們是絕對必須的。
不過,恩,這些你早都知道了…
所以你對此是怎麼做的?傳統方法告訴我們,最好的消除全局策略是創建少數作為潛在模組和子系統的實際命名空間的全局物件。我將探索幾種有關命名空間的方式,並以我基於 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)!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

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

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

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

熱門話題

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

JavaScript中的HTTP狀態碼取得方法簡介:在進行前端開發中,我們常常需要處理與後端介面的交互,而HTTP狀態碼就是其中非常重要的一部分。了解並取得HTTP狀態碼有助於我們更好地處理介面傳回的資料。本文將介紹使用JavaScript取得HTTP狀態碼的方法,並提供具體程式碼範例。一、什麼是HTTP狀態碼HTTP狀態碼是指當瀏覽器向伺服器發起請求時,服務

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數
