自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

JavaScript組件模式深入淺出

開發(fā) 前端
“組件模式”是一種很常用的Javascript編碼模式。雖然已經(jīng)被廣泛的應(yīng)用,但是還有一些高級(jí)的用途沒(méi)有被關(guān)注。在這邊文章里,我將針對(duì)幾個(gè)比較特別的話題進(jìn)行簡(jiǎn)單的闡述,其中的一些我認(rèn)為應(yīng)該是第一次被提及。

“組件模式”是一種很常用的Javascript編碼模式。雖然已經(jīng)被廣泛的應(yīng)用,但是還有一些高級(jí)的用途沒(méi)有被關(guān)注。在這邊文章里,我將針對(duì)幾個(gè)比較特別的話題進(jìn)行簡(jiǎn)單的闡述,其中的一些我認(rèn)為應(yīng)該是***次被提及。

基礎(chǔ)

我們從一個(gè)簡(jiǎn)單的組件模式開始說(shuō)起,這個(gè)模式現(xiàn)在已經(jīng)非常流行,最初是3年前由雅虎YUI的Eric Miraglia在其博客中提出的。如果你已經(jīng)對(duì)這個(gè)模式很熟悉了,那么可以直接跳到“高級(jí)模式”一節(jié)。

匿名閉包(Anonymous Closures)

這是使得模式可以正常工作的語(yǔ)言基礎(chǔ),也實(shí)在是javascript最為實(shí)用的特性之一。我們可以簡(jiǎn)單的創(chuàng)建一個(gè)匿名函數(shù),并且立刻執(zhí)行它。所有運(yùn)行在該函數(shù)里的代碼叫做一個(gè)閉包,它提供了在整個(gè)應(yīng)用程序生命周期中都有效的數(shù)據(jù)隱私控制以及狀態(tài)保存功能。

  1. (function () {        
  2. // ... all vars and functions are in this scope only          
  3. // still maintains access to all globals  
  4. }()); 

請(qǐng)注意()包圍了匿名函數(shù),這是語(yǔ)法的需要,因?yàn)橐詅unction開頭的語(yǔ)句會(huì)被編譯器認(rèn)為的函數(shù)的定義,而加上()就變?yōu)榱藙?chuàng)建了一個(gè)函數(shù)表達(dá)式。

全局導(dǎo)入(Global Import)

JavaScript 有一個(gè)大家熟知的特性叫做implied globals,就是當(dāng)使用一個(gè)變量的時(shí)候,解釋器會(huì)沿著作用域鏈一直向上查找這個(gè)變量的定義,如果沒(méi)找到,這個(gè)變量就會(huì)自動(dòng)成為一個(gè)全局(global)變量。這意味著在一個(gè)匿名閉包里去創(chuàng)建一個(gè)全局變量變得非常簡(jiǎn)單。

但是,這產(chǎn)生了很難管理的代碼問(wèn)題,因?yàn)槲覀儫o(wú)法明顯的知道一個(gè)給定的文件里究竟哪些變量是全局的

(譯者注:如果允許這么隱晦的寫法來(lái)創(chuàng)建全局變量,則代碼中使用的變量,很難知道是全局的還是局部的。)

幸運(yùn)的是,我們的匿名函數(shù)提供了一個(gè)很簡(jiǎn)單的修改來(lái)解決這個(gè)問(wèn)題。我們傳入一個(gè)全局對(duì)象作為匿名函數(shù)的參數(shù),我們利用這個(gè)參數(shù)導(dǎo)入我們的變量到全局對(duì)象中,這樣做比隱式的聲明全局變量要干凈和快速的多。下面是一個(gè)例子

  1. (function ($, YAHOO) {          
  2. // now have access to globals jQuery (as $) and YAHOO in this code  
  3. }(jQuery, YAHOO)); 

模塊導(dǎo)出(Module Export)

有時(shí)候我們不只是想定義一個(gè)模塊,還想直接使用它,我們可以使用匿名函數(shù)的返回值來(lái)實(shí)現(xiàn)。如果這么做,就是實(shí)現(xiàn)了一個(gè)基本的“組件模式”,看下面的例子:

  1. var MODULE = (function () {          
  2. var my = {},privateVariable = 1;                 
  3.  function privateMethod() {                  
  4. // ...          
  5. }  
  6. my.moduleProperty = 1;         
  7.  my.moduleMethod = function () {                  
  8. // ...          
  9. };                  
  10. return my;  
  11. }()); 

要注意的是我們定義了一個(gè)全局組件名字叫“MODULE”,他有兩個(gè)屬性:一個(gè)方法MODULE.moduleMethod以及一個(gè)屬性MODULE.moduleProperty。并且,它通過(guò)匿名函數(shù)所在的閉包維護(hù)了一組私有的內(nèi)部狀態(tài)

(譯者注:privateVariable變量和privateMethod方法都是私有的,外部無(wú)法訪問(wèn))。

這樣的話,我們就可以用上面的模式簡(jiǎn)單的導(dǎo)入需要的全局變量。

高級(jí)模式(Advanced Patterns)

上面的模式已經(jīng)可以解決應(yīng)用中的許多問(wèn)題,但是我們還可以在這個(gè)基礎(chǔ)上擴(kuò)展出很多強(qiáng)大的,易擴(kuò)展的結(jié)構(gòu)。讓我們一個(gè)個(gè)看一下,繼續(xù)用我們的組件“MODULE”做例子

增益模式(Augmentation)

使用上面的模式的缺點(diǎn)和限制之一,就是整個(gè)模塊必須在一個(gè)文件里。任何在大型項(xiàng)目中工作的人都會(huì)意識(shí)到能將代碼拆分成多個(gè)文件帶來(lái)的價(jià)值。幸運(yùn)的是,我們有一個(gè)不錯(cuò)的解決方案叫做“增益組件”。首先,我們導(dǎo)入組件,然后添加屬性,然后再將其導(dǎo)出。下面是一個(gè)例子,為我們的MODULE組件添加增益特性:

  1. var MODULE = (function (my) {          
  2. my.anotherMethod = function () {                  
  3. // added method...          
  4. };          
  5. return my;  
  6. }(MODULE)); 

我們使用var關(guān)鍵字來(lái)保持一致性(盡管這不是必須的)。這段代碼執(zhí)行過(guò)后,我們的組件就增加了一個(gè)公開的方法叫做MODULE.anotherMethod。這個(gè)增加的文件也會(huì)同時(shí)保持它自己的私有狀態(tài)。

(譯者注:通過(guò)增益模式,一個(gè)雷被切分成獨(dú)立的文件,每個(gè)文件關(guān)注它內(nèi)部需要的方法和屬性,并且當(dāng)所有文件合并執(zhí)行后,可以成為一個(gè)完整的組件)

松耦合增益(Loose Augmentation)

我們上面的例子有一個(gè)缺點(diǎn),就是需要MODULE模塊先被創(chuàng)建,然后再執(zhí)行子文件中的增益。這是一種緊耦合的做法。javascript性能優(yōu)化中通常的做法是腳本的異步加載,這樣我們就可以創(chuàng)建由多個(gè)文件組成的易擴(kuò)展的組件,并且他們可以以任何順序來(lái)加載,這叫做松耦合增益模式:

  1. var MODULE = (function (my) {          
  2. // add capabilities...                 
  3.  return my;  
  4. }(MODULE || {})); 

在這個(gè)模式中,var關(guān)鍵字是必須的。注意我們的import點(diǎn)(參數(shù))會(huì)自動(dòng)判斷組件是否存在,否則就創(chuàng)建一個(gè)空組件。這意味著你可以使用一些異步加載工具比如LABjs來(lái)并行加載你所有的js組件,而不需要block頁(yè)面。

緊耦合增益(Tight Augmentation)

“松耦合增益”模式非常棒,不過(guò)它也有一些限制,最重要的一個(gè)就是無(wú)法重寫屬性。你也無(wú)法在初始化組件的時(shí)候使用其他文件的內(nèi)容(因?yàn)榧虞d順序無(wú)法保證),“緊耦合增益模式”需要一個(gè)有序的加載順序,但是允許你重寫其他文件的內(nèi)容,這是一個(gè)簡(jiǎn)單的例子:

  1. var MODULE = (function (my) {          
  2. var old_moduleMethod = my.moduleMethod;                  
  3. my.moduleMethod = function () {                  
  4. // method override, has access to old through old_moduleMethod...         
  5.  };                 
  6.  return my;  
  7. }(MODULE)); 

這里我們重寫了 MODULE.moduleMethod,同時(shí)也保存了舊的 MODULE.moduleMethod方法的引用(如果需要的話)

克隆和繼承(Cloning and Inheritance)

  1. var MODULE_TWO = (function (old) {          
  2. var my = {}, key;                  
  3. for (key in old) {                  
  4. if (old.hasOwnProperty(key)) {                          
  5. my[key] = old[key];                  
  6. }          
  7. }                  
  8. var super_moduleMethod = old.moduleMethod;          
  9. my.moduleMethod = function () {                  
  10. // override method on the clone, access to super through super_moduleMethod        };                  
  11. return my;  
  12. }(MODULE)); 

這種模式也許是最沒(méi)有擴(kuò)展性的選項(xiàng)了。它雖然看上去讓代碼更簡(jiǎn)潔,但是帶來(lái)的是擴(kuò)展性的損失。我們上面的代碼中,所有的屬性和方法都不是副本,他們以“一個(gè)對(duì)象2個(gè)引用”的方式存在。修改其中一個(gè)都會(huì)影響到另外一個(gè)。

跨文件私有狀態(tài)(Cross-File Private State)

將組件分割到多個(gè)文件中的另外一個(gè)限制,就是每個(gè)文件只能訪問(wèn)他自己的私有狀態(tài),而沒(méi)有權(quán)限訪問(wèn)其他文件的私有數(shù)據(jù)。這個(gè)問(wèn)題可以解決,下面是一個(gè)“松耦合增益模式”的跨文件訪問(wèn)私有狀態(tài)的版本:

  1. var MODULE = (function (my) {          
  2. var _private = my._private = my._private || {},                  
  3. _seal = my._seal = my._seal || function () {                          
  4. delete my._private;                          
  5. delete my._seal;                          
  6. delete my._unseal;                  
  7. },                  
  8. _unseal = my._unseal = my._unseal || function () {                          
  9. my._private = _private;                         
  10.  my._seal = _seal;                          
  11. my._unseal = _unseal;                 
  12.  };                  
  13. // permanent access to _private, _seal, and _unseal                  
  14. return my;  
  15. }(MODULE || {})); 

現(xiàn)在任何文件都可以在本地變量_private中設(shè)置屬性,并且會(huì)立即將設(shè)置結(jié)果反饋給其他文件。一旦組件加載完成,應(yīng)用程序應(yīng)該調(diào)用 MODULE._seal()方法,這個(gè)方法會(huì)阻止外部程序訪問(wèn)內(nèi)部屬性_private。如果這個(gè)組件被其他文件進(jìn)行了擴(kuò)展(增益),則可在加載新的文件之前,調(diào)用_unseal()方法解封,然后在文件加載完之后調(diào)用_seal()再次將類對(duì)外部屏蔽。

(譯者注:注意_unseal方法會(huì)在對(duì)象里添加1個(gè)公開的屬性和2個(gè)公開方法,其他文件就可以在my對(duì)象中隊(duì)private屬性進(jìn)行擴(kuò)展,然后利用_seal()方法刪除公開的屬性,保持對(duì)象的密封性)

這個(gè)模式是今天我在工作的時(shí)候想到的,我沒(méi)有在其他地方見過(guò)這種用法,我認(rèn)為這是一種十分有用的模式。

子模塊(Sub-modules)

Our final advanced pattern is actually the simplest. There are many good cases for creating sub-modules. It is just like creating regular modules:

我們***的一個(gè)高級(jí)模式實(shí)際上是最簡(jiǎn)單的,創(chuàng)建子模塊有很多的好處,創(chuàng)建子模塊就和創(chuàng)建普通模塊一樣:

  1. MODULE.sub = (function () {          
  2. var my = {};         
  3.  // ...                  
  4. return my;  
  5. }()); 

雖然這很簡(jiǎn)單,但我還是認(rèn)為子模塊應(yīng)該包含進(jìn)來(lái),因?yàn)樽幽K擁有所有正常模塊有的高級(jí)特性,包括增益和私有數(shù)據(jù)保存。

結(jié)論

大多數(shù)高級(jí)模式都可以結(jié)合起來(lái)使用,如果是我的話,我比較喜歡把“松耦合增益”、“私有狀態(tài)保存”、“子模式”結(jié)合起來(lái)使用

我這篇文字并沒(méi)有討論性能相關(guān)的內(nèi)容,不過(guò)我想簡(jiǎn)單的說(shuō)一下:組件模式是對(duì)性能有好處的。因?yàn)樗_實(shí)讓下載快了很多:使用“松耦合增益”模式可以讓腳本并行的無(wú)阻塞加載,這加快了下載速度。整體初始化完成的時(shí)間也許比其他方法慢了一些,不過(guò)這是值得的。

作為結(jié)尾,這里有一個(gè)子模塊的例子,他動(dòng)態(tài)的加載自己到它的父模塊中。這個(gè)模式允許整個(gè)模塊并行的加載自己,以及自己的子模塊。

譯文出自:刺客之家的博客

原文鏈接:http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth

【編輯推薦】

  1. JavaScript面向?qū)ο缶幊?/a>
  2. JavaScript繼承詳解
  3. 早該知道的7個(gè)JavaScript技巧
  4. JavaScript MVC框架backbone.js初探
  5. 8個(gè)***的JavaScript腳本資源強(qiáng)烈推薦

 

責(zé)任編輯:陳貽新 來(lái)源: 刺客之家的博客
相關(guān)推薦

2022-09-26 09:01:15

語(yǔ)言數(shù)據(jù)JavaScript

2023-12-04 13:22:00

JavaScript異步編程

2010-07-16 09:11:40

JavaScript內(nèi)存泄漏

2022-10-31 09:00:24

Promise數(shù)組參數(shù)

2022-12-02 09:13:28

SeataAT模式

2011-05-30 14:41:09

Javascript閉

2021-03-16 08:54:35

AQSAbstractQueJava

2011-07-04 10:39:57

Web

2012-02-07 15:09:03

Android核心組件Service

2012-02-07 14:37:01

Android核心組件Service

2012-02-07 15:16:01

Android核心組件Service

2012-02-07 15:29:17

Android核心組件Service

2012-02-07 14:45:52

Android核心組件Service

2009-06-18 10:23:03

Javascript 基本框架

2022-05-26 09:20:01

JavaScript原型原型鏈

2009-06-22 15:34:00

Javascript

2017-07-02 18:04:53

塊加密算法AES算法

2019-01-07 15:29:07

HadoopYarn架構(gòu)調(diào)度器

2021-07-20 15:20:02

FlatBuffers阿里云Java

2012-05-21 10:06:26

FrameworkCocoa
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)