javascript
javascript 模块模式
2019獨角獸企業(yè)重金招聘Python工程師標準>>>
模塊模式是JavaScript一種常用的編碼模式。這是一般的理解,但也有一些高級應(yīng)用沒有得到很多關(guān)注。在本文中,我將回顧基礎(chǔ)知識,瀏覽一些不錯的高級技巧,甚至我認為是原生基礎(chǔ)的。
基礎(chǔ)知識
首先我們開始簡單概述模型模式。如果你已經(jīng)很熟悉模型模式,可以直接閱讀“高級模式”。
匿名閉包
這是一切成為可能的基礎(chǔ),也是JavaScript最好的特性。我們將簡單的創(chuàng)建匿名函數(shù),并立即執(zhí)行。所有函數(shù)內(nèi)部代碼都在閉包(closure)內(nèi)。它提供了整個應(yīng)用生命周期的私有和狀態(tài)。
?
注意匿名函數(shù)周圍的()。這是語言的要求。關(guān)鍵字function一般認為是函數(shù)聲明,包括()就是函數(shù)表達式。
引入全局
JavaScript有個特性,稱為隱性全局。使用變量名稱時,解釋器會從作用域向后尋找變量聲明。如果沒找到,變量會被假定入全局(以后可以全局調(diào)用)。如果會被分配使用,在還不存在時全局創(chuàng)建它。這意味著在匿名函數(shù)里使用全局變量很簡單。不幸的是,這會導致代碼難以管理,文件中不容易區(qū)分(對人而言)哪個變量是全局的。
幸好,匿名函數(shù)還有一個不錯的選擇。全局變量作為參數(shù)傳遞給匿名函數(shù)。將它們引入我們的代碼中,既更清晰,又比使用隱性全局更快。下面是一個例子:
?
模塊出口
有時你不只想用全局變量,但你需要先聲明他們(模塊的全局調(diào)用)。我們用匿名函數(shù)的返回值,很容易輸出他們。這樣做就完成了基本的模塊模式。以下是一個完整例子:
?
注意,我們聲明了一個全局模塊MODULE,有兩個公開屬性:方法MODULE.moduleMethod和屬性MODULE.moduleProperty。而且,匿名函數(shù)的閉包還維持了私有內(nèi)部狀態(tài)。同時學會之上的內(nèi)容,我們就很容易引入需要的全局變量,和輸出到全局變量。
高級模式
對許多用戶而言以上的還不足,我們可以采用以下的模式創(chuàng)造強大的,可擴展的結(jié)構(gòu)。讓我們使用MODULE模塊,一個一個繼續(xù)。
擴充
模塊模式的一個限制是整個模塊必須在一個文件里。任何人都了解長代碼分割到不同文件的必要。還好,我們有很好的辦法擴充模塊。(在擴充文件)首先我們引入模塊(從全局),給他添加屬性,再輸出他。下面是一個例子擴充模塊:
?
我們再次使用var關(guān)鍵字以保持一致性,雖然其實沒必要。代碼執(zhí)行后,模塊獲得一個新公開方法MODULE.anotherMethod。擴充文件沒有影響模塊的私有內(nèi)部狀態(tài)。
松耦合擴充
上面的例子需要我們首先創(chuàng)建模塊,然后擴充它,這并不總是必要的。提升JavaScript應(yīng)用性能最好的操作就是異步加載腳本。因而我們可以創(chuàng)建靈活多部分的模塊,可以將他們無順序加載,以松耦合擴充。每個文件應(yīng)有如下的結(jié)構(gòu):
?
這個模式里,var語句是必須的,以標記引入時不存在會創(chuàng)建。這意味著你可以像LABjs一樣同時加載所有模塊文件而不被阻塞。
緊耦合擴充
雖然松耦合很不錯,但模塊上也有些限制。最重要的,你不能安全的覆寫模塊屬性(因為沒有加載順序)。初始化時也無法使用其他文件定義的模塊屬性(但你可以在初始化后運行)。緊耦合擴充意味著一組加載順序,但是允許覆寫。下面是一個例子(擴充最初定義的MODULE):
?
我們覆寫的MODULE.moduleMethod,但依舊保持著私有內(nèi)部狀態(tài)。
克隆和繼承
?
這種方式也許最不靈活。他可以實現(xiàn)巧妙的組合,但是犧牲了靈活性。正如我寫的,對象的屬性或方法不是拷貝,而是一個對象的兩個引用。修改一個會影響其他。這可能可以保持遞歸克隆對象的屬性固定,但無法固定方法,除了帶eval的方法。不過,我已經(jīng)完整的包含了模塊。(其實就是做了一次淺拷貝)。
跨文件私有狀態(tài)
一個模塊分割成幾個文件有一個嚴重缺陷。每個文件都有自身的私有狀態(tài),且無權(quán)訪問別的文件的私有狀態(tài)。這可以修復的。下面是一個松耦合擴充的例子,不同擴充文件之間保持了私有狀態(tài):
?
何文件都可以在本地的變量_private中設(shè)置屬性,他會對別的擴充立即生效(即初始化時所有擴充的私有狀態(tài)都保存在_private變量,并被my._private輸出)。模塊完全加載了,應(yīng)用調(diào)用MODULE._seal()方法阻止對私有屬性的讀取(干掉my._private輸出)。如果此后模塊又需要擴充,帶有一個私有方法。加載擴充文件前調(diào)用MODULE._unseal()方法(恢復my._private,外部恢復操作權(quán)限)。加載后調(diào)用再seal()。
這個模式一直隨我工作至今,我還沒看到別的地方這樣做的。我覺得這個模式很有用,值得寫上。
子模塊
最后的高級模式實際上最簡單。有很多好方法創(chuàng)建子模塊。和創(chuàng)建父模塊是一樣的:
?
雖然很簡單,但我還是提一下。子模塊有所有正常模塊的功能,包括擴充和私有狀態(tài)。
總結(jié)
大多數(shù)高級模式可以互相組合成更多有用的模式。如果要我提出一個復雜應(yīng)用的設(shè)計模式,我會組合松耦合、私有狀態(tài)和子模塊。
這里我還沒有涉及性能,不過我有個小建議:模塊模式是性能增益的。他簡化了許多,加快代碼下載。松耦合可以無阻塞并行下載,等價于提高下載速度??赡艹跏蓟葎e的方法慢一點,但值得權(quán)衡。只要全局正確的引入,運行性能不會有任何損失,可能還因為局部變量和更少的引用,加快子模塊的加載。
最后,一個例子動態(tài)加載子模塊到父模塊(動態(tài)創(chuàng)建)中。這里就不用私有狀態(tài)了,其實加上也很簡單。這段代碼允許整個復雜分成的代碼核心及其子模塊等平行加載完全。
?
轉(zhuǎn)載于:https://my.oschina.net/niejianbo/blog/857600
總結(jié)
以上是生活随笔為你收集整理的javascript 模块模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hangfire 任务调度
- 下一篇: Web服务(Apache、Nginx、T