摘要:原文鏈接譯文原鏈譯中的命名空間全局變量應(yīng)該由有系統(tǒng)范圍相關(guān)性的對(duì)象們保留,并且它們的命名應(yīng)該避免含糊并盡量減少命名沖突的風(fēng)險(xiǎn)。其他的考慮我希望避免命名空間嵌套。因?yàn)椴]有正式的命名空間結(jié)構(gòu),所以有很多自然形成的方法。
原文鏈接: Namespacing in JavaScript
譯文原鏈: 【譯】JavaScript 中的命名空間
全局變量應(yīng)該由有系統(tǒng)范圍相關(guān)性的對(duì)象們保留,并且它們的命名應(yīng)該避免含糊并盡量減少命名沖突的風(fēng)險(xiǎn)。在實(shí)踐中,這意味著你應(yīng)該避免創(chuàng)建全局對(duì)象,除非它們是絕對(duì)必須的。
不過,恩,這些你早都知道了……
所以你對(duì)此是怎么做的?傳統(tǒng)方法告訴我們,最好的消除全局策略是創(chuàng)建少數(shù)作為潛在模塊和子系統(tǒng)的實(shí)際命名空間的全局對(duì)象。我將探索幾種有關(guān)命名空間的方式,并以我基于 James Edwards 最近的一篇文章得到的一個(gè)優(yōu)雅、安全和靈活的解決方案結(jié)束。
靜態(tài)命名空間我用靜態(tài)命名空間作為那些命名空間標(biāo)簽實(shí)際上硬編碼的解決方案的涵蓋性術(shù)語(yǔ)。是的,你可以將一個(gè)命名空間重新分配給另一個(gè),不過新的命名空間將會(huì)引用和舊的那一個(gè)同樣的對(duì)象。
1.通過直接分配最基礎(chǔ)的方法。這樣非常冗長(zhǎng),并且如果你還想重命名這些命名空間,你就有得活兒干了。不過它是安全和清楚明白的。
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引用兄弟屬性來使將來的維護(hù)更輕松一些,不過這有一點(diǎn)冒險(xiǎn)因?yàn)闆]有什么能阻止你的那些命名空間里的方法被重新分配。
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.使用對(duì)象字面量
現(xiàn)在我們只需要引用命名空間名一次,因此之后改變名字更簡(jiǎn)單了一些(假設(shè)你還沒反復(fù)引用這個(gè)命名空間)。仍有一個(gè)危險(xiǎn)是this的值可能會(huì)拋出一個(gè)『驚喜』 - 不過假設(shè)在一個(gè)對(duì)象字面結(jié)構(gòu)里定義的對(duì)象不會(huì)被重新分配相對(duì)安全一點(diǎn)。
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, 03.模塊模式
我發(fā)現(xiàn)自己最近用模塊模式更多。邏輯被一個(gè)方法包裝從全局域隔離開了(通常是自調(diào)用的),它返回一個(gè)代表這個(gè)模塊公開接口的對(duì)象。通過立即調(diào)用這個(gè)方法并分配結(jié)果給一個(gè)命名空間變量,我們就鎖住了這個(gè)命名變量中模塊的 API。此外,任何沒有包括在返回值中的變量將永遠(yuǎn)保持私有,只對(duì)引用他們的公開方法可見。
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
如上對(duì)象字面量例子,命名空間名字可以輕易更換,不過還有額外優(yōu)勢(shì):對(duì)象字面量是四班的 - 它全是關(guān)于屬性分配,沒有支持邏輯的空間。此外,所有屬性必須被初始化,并且屬性值無(wú)法輕易跨對(duì)象引用(因此,比如,內(nèi)部閉包就不可能使用了)。模塊模式?jīng)]有任何上述約束,并且給我們額外的隱私福利。
動(dòng)態(tài)命名空間我們也可以將這一節(jié)稱為命名空間注入。命名空間由一個(gè)直接引用方法包裝內(nèi)部的代理代表 - 這意味著我們不再需要打包分配給命名空間的返回值。這讓命名空間定義變得更靈活并且讓擁有多個(gè)存在于獨(dú)立命名空間中(或者甚至在全局上下文中)的模塊的獨(dú)立實(shí)例。動(dòng)態(tài)命名空間支持模塊模式的全部特征并附加直觀和可讀性強(qiáng)的優(yōu)勢(shì)。
4.提供命名空間參數(shù)在這里我們只是將命名空間作為參數(shù)傳給自調(diào)用方法。變量id是私有的,因?yàn)樗]有被分配給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設(shè)置給全局對(duì)象(通過一個(gè)字的改變!)。這是庫(kù)主們的巨大財(cái)富 - 他們可以將他們的特性包裝在一個(gè)自調(diào)用函數(shù)中,然后讓用戶來決定它們是不是全局的(John Resig 在他寫 JQuery 時(shí)就是一個(gè)這個(gè)理論的早期采用者)。
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, 05.用this作為命名空間代理
James Edwads 最近發(fā)布的一篇文章激起了我的興趣。《My Favorite JavaScript Design Patter》 顯然被很多評(píng)論者誤解了,他們認(rèn)為他可能也是借助于模塊模式。這篇文章宣傳了多種技術(shù)(可能導(dǎo)致了讀者的迷惑),但是在它的核心部分是一點(diǎn)我已經(jīng)修改并呈現(xiàn)為一個(gè)命名空間工具的很天才的東西。
這個(gè)模式的美就在于它僅僅是按照這個(gè)語(yǔ)言被設(shè)計(jì)的方式使用 - 不多不少、不投機(jī)也不取巧。此外因?yàn)槊臻g是通過this關(guān)鍵字(它在給定的執(zhí)行上下文中是不變的)注入的,它不可能被意外修改。
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 提供了與上下文和參數(shù)天然的隔離 - 因此給模塊創(chuàng)建者傳遞附加參數(shù)非常干凈。下面的例子表明了這一點(diǎn),并且展示了如何獨(dú)立于多個(gè)命名空間來運(yùn)行模塊。
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
當(dāng)然如果我們?nèi)绻覀冃枰粋€(gè)全局 id 生成器,非常簡(jiǎn)單……
nextIdMod(); window.console && console.log( next(), next(), reset(), next() ) //0, 1, undefined, 0
這個(gè)我們作為例子使用的 id 生成器工具并沒有表現(xiàn)出這個(gè)模式的全部潛力。通過包裹一整個(gè)庫(kù)和使用this關(guān)鍵字作為命名空間的替身,我們使得用戶在任何他們選擇的上下文中運(yùn)行這個(gè)庫(kù)很輕松(包括全局上下文)。
//library code var protoQueryMooJo = function() { //everything } //user code var thirdParty = {}; protoQueryMooJo.apply(thirdParty);其他的考慮
我希望避免命名空間嵌套。它們很難追蹤(對(duì)人和電腦都是)并且它們會(huì)讓你的代碼因?yàn)橐恍﹣y七八糟的東西變得很多。如 Peter Michaux 指出的,深度嵌套的命名空間可能是那些視圖重新創(chuàng)建他們熟悉和熱愛的長(zhǎng)包鏈的老派 Java 開發(fā)者的遺產(chǎn)。
通過 .js 文件來固定一個(gè)多帶帶的命名空間也是可以的(雖然只能通過命名空間注入或者直接分配每一個(gè)變量),不過你應(yīng)該對(duì)依賴謹(jǐn)慎些。此外將命名空間綁定到文件上可以幫助讀者更輕易弄清整個(gè)代碼。
因?yàn)?JavaScript 并沒有正式的命名空間結(jié)構(gòu),所以有很多自然形成的方法。這個(gè)調(diào)查只詳細(xì)說明了其中的一部分,可能有更好的技術(shù)我沒有發(fā)現(xiàn)。我很樂意知道它們。
更多文章James Edwards: My Favorite JavaScript Design Pattern
Peter Michaux: JavaScript Namespacing
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/79736.html
摘要:前綴命名空間如果命名空間的目的是避免沖突的話。語(yǔ)言程序經(jīng)常使用前綴命名空間。我認(rèn)為前綴命名空間是中最清楚明白的命名空間系統(tǒng)。對(duì)象命名空間的一個(gè)問題是它會(huì)導(dǎo)致與面向?qū)ο笙鬟f混淆。嵌套命名空間的幻覺在中也存在。 原文鏈接:《JavaScript Namespacing》譯文原鏈:【譯】JavaScript 命名空間 JavaScript 中有很多可以給你的對(duì)象安全分配命名空間的方法。這...
摘要:原文鏈接原文作者你想知道的關(guān)于作用域的一切譯中有許多章節(jié)是關(guān)于的但是對(duì)于初學(xué)者來說甚至是一些有經(jīng)驗(yàn)的開發(fā)者這些有關(guān)作用域的章節(jié)既不直接也不容易理解這篇文章的目的就是為了幫助那些想更深一步學(xué)習(xí)了解作用域的開發(fā)者尤其是當(dāng)他們聽到一些關(guān)于作用域的 原文鏈接: Everything you wanted to know about JavaScript scope原文作者: Todd Mott...
摘要:比如,我們可以監(jiān)聽事件由實(shí)例發(fā)出,然后在任何瀏覽器中就是變化的時(shí)候都會(huì)得到通知,如下所示每一個(gè)作用域?qū)ο蠖紩?huì)有這個(gè)方法,可以用來注冊(cè)一個(gè)作用域事件的偵聽器。這個(gè)函數(shù)所扮演的偵聽器在被調(diào)用時(shí)會(huì)有一個(gè)對(duì)象作為第一個(gè)參數(shù)。 上一篇:【譯】《精通使用AngularJS開發(fā)Web App》(二) 下一篇:【譯】《精通使用AngularJS開發(fā)Web App》(四) 書名:Mastering W...
摘要:更新日志應(yīng)對(duì)添加以編程方式收集性能測(cè)量。在和在將棄用為常見攻擊面。添加對(duì)事件的支持。在從調(diào)用時(shí)發(fā)出警告,創(chuàng)建循環(huán)。在和從錯(cuò)誤的渲染器使用時(shí)發(fā)出警告。 2019年8月8日,我們發(fā)布了React 16.9。它包含幾個(gè)新功能,錯(cuò)誤修正和新的棄用警告,以幫助準(zhǔn)備未來的主要版本。 showImg(https://segmentfault.com/img/bVbwoB5?w=1728&h=666)...
摘要:更新日志應(yīng)對(duì)添加以編程方式收集性能測(cè)量。在和在將棄用為常見攻擊面。添加對(duì)事件的支持。在從調(diào)用時(shí)發(fā)出警告,創(chuàng)建循環(huán)。在和從錯(cuò)誤的渲染器使用時(shí)發(fā)出警告。 2019年8月8日,我們發(fā)布了React 16.9。它包含幾個(gè)新功能,錯(cuò)誤修正和新的棄用警告,以幫助準(zhǔn)備未來的主要版本。 showImg(https://segmentfault.com/img/bVbwoB5?w=1728&h=666)...
閱讀 1004·2021-11-25 09:43
閱讀 1672·2019-08-30 13:59
閱讀 1589·2019-08-30 11:22
閱讀 2123·2019-08-30 11:06
閱讀 1299·2019-08-28 17:51
閱讀 3717·2019-08-26 12:12
閱讀 778·2019-08-26 12:11
閱讀 443·2019-08-26 12:10