JavaScript命名空間模式實(shí)例詳解
本文實(shí)例講述了JavaScript命名空間模式。分享給大家供大家參考,具體如下:
前言
命名空間可以被認(rèn)為是唯一標(biāo)識符下代碼的邏輯分組。為什么會(huì)出現(xiàn)命名空間這一概念呢?因?yàn)榭捎玫膯卧~數(shù)太少,并且不同的人寫的程序不可能所有的變量都沒有重名現(xiàn)象。在JavaScript中,命名空間可以幫助我們防止與全局命名空間下的其他對象或變量產(chǎn)生沖突。命名空間也有助于組織代碼,有更強(qiáng)的可維護(hù)性和可讀性。本文旨在探討JavaScript里的幾種常見命名空間模式,為我們提供一個(gè)思路。
JavaScript執(zhí)行環(huán)境有很多獨(dú)特之處,全局變量和函數(shù)的使用就是其中之一。JavaScript的執(zhí)行環(huán)境由各種各樣的全局變量構(gòu)成,這些全局變量先于函數(shù)執(zhí)行環(huán)境而創(chuàng)建。這些全局變量都掛載于“全局對象”下,在瀏覽器中,window對象就等同于全局對象。那么,在全局作用域中聲明的任何變量和函數(shù)都是window對象的屬性,當(dāng)名稱有沖突時(shí),就會(huì)產(chǎn)生一些不可控的問題。全局變量會(huì)帶來以下問題:
命名沖突
代碼的脆弱性
難以測試
在編程開發(fā)中合理的使用命名空間,可以避免相同的變量或?qū)ο竺Q產(chǎn)生的沖突。而且,命名空間也有助于組織代碼,有更強(qiáng)的可維護(hù)性和可讀性。JavaScript中雖然沒有提供原生的命名空間支持,但我們可以使用其他的方法(對象和閉包)實(shí)現(xiàn)類似的效果。下面就是一些常見的命名空間模式:
1.單一全局變量
JavaScript中一個(gè)流行的命名空間模式是選擇一個(gè)全局變量作為主要的引用對象。因?yàn)槊總€(gè)可能的全局變量都成為唯一全局變量的屬性,也就不用再創(chuàng)建多個(gè)全局變量,那么也就避免了和其他聲明的沖突。
單一全局變量模式已經(jīng)在不少的JavaScript類庫中使用,如:
- YUI定義了唯一的YUI全局對象
- jQuery定義了和jQuery,和jQuery,由其他類庫使用時(shí)使用jQuery
- Dojo定義了一個(gè)Dojo全局變量
- Closure類庫定義了一個(gè)goog全局對象
- Underscore類庫定義了一個(gè)_ 全局對象
示例如下:
var myApplication = (function() {
function() {
// ***
},
return {
// **
}
})();
雖然單一全局變量模式適合某些情況,但其最大的挑戰(zhàn)是確保單一全局變量在頁面中是唯一使用的,不會(huì)發(fā)生命名沖突。
2.命名空間前綴
命名空間前綴模式其思路非常清晰,就是選擇一個(gè)獨(dú)特的命名空間,然后在其后面聲明聲明變量、方法和對象。示例如下:
var = myApplication_propertyA = {};
var = myApplication_propertyA = {};
function myApplication_myMethod() {
// ***
}
從某種程度上來說,它確實(shí)減少了命名沖突的發(fā)生概率,但其并沒有減少全局變量的數(shù)目。當(dāng)應(yīng)用程序規(guī)模擴(kuò)大時(shí),就會(huì)產(chǎn)生很多的全局變量。在全局命名空間內(nèi),這種模式對其他人都沒有使用的這個(gè)前綴有很強(qiáng)的依賴,而且有些時(shí)候也不好判斷是否有人已經(jīng)使用某個(gè)特殊前綴,在使用這種模式時(shí)一定要特別注意。
3.對象字面量表示法
對象字面量模式可以認(rèn)為是包含一組鍵值對的對象,每一對鍵和值由冒號分隔,鍵也可以是代碼新的命名空間。示例如下:
var myApplication = {
// 可以很容易的為對象字面量定義功能
getInfo:function() {
// ***
},
// 可以進(jìn)一步支撐對象命名空間
models:{},
views:{
pages:{}
},
collections:{}
};
與為對象添加屬性一樣,我們也可以直接將屬性添加到命名空間。對象字面量方法不會(huì)污染全局命名空間,并在邏輯上協(xié)助組織代碼和參數(shù)。并且,這種方式可讀性和可維護(hù)性非常強(qiáng),當(dāng)然我們在使用時(shí)應(yīng)當(dāng)進(jìn)行同名變量的存在性測試,以此來避免沖突。下面是一些常用的檢測方法:
var myApplication = myApplication || {};
if(!myApplication) {
myApplication = {};
}
window.myApplication || (window.myApplication || {});
// 針對jQuery
var myApplication = $.fn.myApplication = function() {};
var myApplication = myApplication === undefined ? {} :myApplication;
對象字面量為我們提供了優(yōu)雅的鍵/值語法,我們可以非常便捷的組織代碼,封裝不同的邏輯或功能,而且可讀性、可維護(hù)性、可擴(kuò)展性極強(qiáng)。
4.嵌套命名空間
嵌套命名空間模式可以說是對象字面量模式的升級版,它也是一種有效的避免沖突模式,因?yàn)榧词挂粋€(gè)命名空間存在,它也不太可能擁有同樣的嵌套子對象。示例如下:
var myApplication = myApplication || {};
// 定義嵌套子對象
myApplication.routers = myApplication.routers || {};
myApplication.routers.test = myApplication.routers.test || {};
當(dāng)然,我們也可以選擇聲明新的嵌套命名空間或?qū)傩宰鳛樗饕龑傩?,如?/p>
myApplication['routers'] = myApplication['routers'] || {};
使用嵌套命名空間模式,可以使代碼易讀且有組織性,而且相對安全,不易產(chǎn)生沖突。其弱點(diǎn)是,如果我們的命名空間嵌套過多,會(huì)增加瀏覽器的查詢工作量,我們可以把要多次訪問的子對象進(jìn)行局部緩存,以此來減少查詢時(shí)間。
5.立即調(diào)用的函數(shù)表達(dá)式
立即調(diào)用函數(shù)(IIFE)實(shí)際上就是匿名函數(shù),被定義后立即被調(diào)用。在JavaScript中,由于變量和函數(shù)都是在這樣一個(gè)只能在內(nèi)部進(jìn)行訪問的上下文中被顯式地定義,函數(shù)調(diào)用提供了一種實(shí)現(xiàn)私有變量和方法的便捷方式。IIFE是用于封裝應(yīng)用程序邏輯的常用方法,以保護(hù)它免受全局名稱空間的影響,其在命名空間方面也可以發(fā)揮其特殊的作用。示例如下:
// 命名空間和undefined作為參數(shù)傳遞,確保:
// 1.命名空間可以在局部修改,不重寫函數(shù)外部上下文
// 2.undefined 的參數(shù)值是確保undefined,避免ES5規(guī)范里定義的undefined
(function (namespace, undefined) {
// 私有屬性
var foo = "foo";
bar = "bar";
// 公有方法和屬性
namespace.foobar = "foobar";
namespace.sayHello = function () {
say("Hello World!");
};
// 私有方法
function say(str) {
console.log("You said:" + str);
};
})(window.namespace = window.namespace || {});
可擴(kuò)展性是任何可伸縮命名空間模式的關(guān)鍵,使用IIFE可以輕松實(shí)現(xiàn)這一目的,我們可以再次使用IIFE給命名空間添加更多的功能。
6.命名空間注入
命名空間注入是IIFE的另一個(gè)變體,從函數(shù)包裝器內(nèi)部為一個(gè)特定的命名空間“注入”方法和屬性,使用this作為命名空間代理。這種模式的優(yōu)點(diǎn)是可以將功能行為應(yīng)用到多個(gè)對象或命名空間。示例如下:
var myApplication = myApplication || {};
myApplication.utils = {};
(function () {
var value = 5;
this.getValue = function () {
return value;
}
// 定義新的子命名空間
this.tools = {};
}).apply(myApplication.utils);
(function () {
this.diagnose = function () {
return "diagnose";
}
}).apply(myApplication.utils.tools);
// 同樣的方式在普通的IIFE上擴(kuò)展功能,僅僅將上下文作為參數(shù)傳遞并修改,而不是僅僅使用this
還有一種使用API來實(shí)現(xiàn)上下文和參數(shù)自然分離的方法,該模式感覺更像是一個(gè)模塊的創(chuàng)建者,但作為模塊,它還提供了一個(gè)封裝解決方案。示例如下:
var ns = ns || {},
ns1 = ns1 || {};
// 模塊、命名空間創(chuàng)建者
var creator = function (val) {
var val = val || 0;
this.next = function () {
return val ++ ;
};
this.reset = function () {
val = 0;
}
}
creator.call(ns);
// ns.next, ns.reset 此時(shí)已經(jīng)存在
creator.call(ns1, 5000);
// ns1包含相同的方法,但值被重寫為5000了
命名空間注入是用于為多個(gè)模塊或命名空間指定一個(gè)類似的功能基本集,但最好是在聲明私有變量或者方法時(shí)再使用它,其他時(shí)候使用嵌套命名空間已經(jīng)足以滿足需要了。
7.自動(dòng)嵌套的命名空間
嵌套命名空間模式可以為代碼單元提供有組織的結(jié)構(gòu)層級,但每次創(chuàng)建一個(gè)層級時(shí),我們也得確保其有相應(yīng)的父層級。當(dāng)層級數(shù)量很大時(shí),會(huì)給我們帶來很大的麻煩,我們不能快速便捷的創(chuàng)建想創(chuàng)建的層級。那么如何解決這個(gè)問題呢?Stoyan Stefanov提出,創(chuàng)建一個(gè)方法,其接收字符串參數(shù)作為一個(gè)嵌套,解析它,并自動(dòng)用所需的對象填充基本名稱空間。下面是這種模式的一種實(shí)現(xiàn):
function extend(ns, nsStr) {
var parts = nsStr.split("."),
parent = ns,
pl;
pl = parts.length;
for (var i = 0; i < pl; i++) {
// 屬性如果不存在,則創(chuàng)建它
if (typeof parent[parts[i]] === "undefined") {
parent[prats[i]] = {};
}
parent = parent[parts[i]];
}
return parent;
}
// 用法
var myApplication = myApplication || {};
var mod = extend(myApplication, "module.module2");
以前我們必須為其命名空間將各種嵌套顯式聲明為對象,現(xiàn)在用上述更簡潔、優(yōu)雅的方式就實(shí)現(xiàn)了。
更多關(guān)于JavaScript相關(guān)內(nèi)容可查看本站專題:《JavaScript常用函數(shù)技巧匯總》、《javascript面向?qū)ο笕腴T教程》、《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》
希望本文所述對大家JavaScript程序設(shè)計(jì)有所幫助。
相關(guān)文章
JS實(shí)現(xiàn)鼠標(biāo)點(diǎn)擊箭頭旋轉(zhuǎn)180度功能
這篇文章主要介紹了JS實(shí)現(xiàn)鼠標(biāo)點(diǎn)擊箭頭旋轉(zhuǎn)180度的效果,通過點(diǎn)擊三角按鈕旋轉(zhuǎn)180度,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2024-02-02
微信小程序如何修改本地緩存key中單個(gè)數(shù)據(jù)的詳解
這篇文章主要介紹了微信小程序如何修改本地緩存key中單個(gè)數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
基于JS實(shí)現(xiàn)導(dǎo)航條flash導(dǎo)航條
flash導(dǎo)航條在網(wǎng)站建設(shè)中應(yīng)用比較廣泛,此種效果給瀏覽者帶來極好的視覺效果,非常棒,下面小編給大家介紹基于JS實(shí)現(xiàn)導(dǎo)航條flash導(dǎo)航條,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧2016-06-06
javascript中直接引用Microsoft的COM生成Word
直接引用Microsoft的COM是可以生成Word的,下面為大家介紹下實(shí)現(xiàn)的javascript代碼2014-01-01
微信小程序獲取音頻時(shí)長與實(shí)時(shí)獲取播放進(jìn)度問題
這篇文章主要介紹了微信小程序獲取音頻時(shí)長與實(shí)時(shí)獲取播放進(jìn)度,文中給大家通過一個(gè)例子介紹了微信小程序音頻長度獲取的問題,感興趣的朋友跟隨腳本之家小編一起看看吧2018-08-08
原生js jquery ajax請求以及jsonp的調(diào)用方法
下面小編就為大家?guī)硪黄鷍s jquery ajax請求以及jsonp的調(diào)用方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08
微信小程序商城分類滾動(dòng)列表錨點(diǎn)的項(xiàng)目實(shí)踐
本文主要介紹了微信小程序商城分類滾動(dòng)列表錨點(diǎn)的項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04

