亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

javascript模塊化編程(轉載)

2019-11-15 02:20:15
字體:
來源:轉載
供稿:網友
javascript模塊化編程(轉載)Javascript 模塊化編程作者: 阮一峰發布時間: 2013-01-08 18:04閱讀: 7632 次推薦: 40 原文鏈接 [收藏]

  隨著網站逐漸變成"互聯網應用程序",嵌入網頁的 Javascript 代碼越來越龐大,越來越復雜。

  網頁越來越像桌面程序,需要一個團隊分工協作、進度管理、單元測試等等......開發者不得不使用軟件工程的方法,管理網頁的業務邏輯。

  Javascript 模塊化編程,已經成為一個迫切的需求。理想情況下,開發者只需要實現核心的業務邏輯,其他都可以加載別人已經寫好的模塊。

  但是,Javascript 不是一種模塊化編程語言,它不支持"類"(class),更遑論"模塊"(module)了。(正在制定中的 ECMAScript 標準第六版,將正式支持"類"和"模塊",但還需要很長時間才能投入實用。)

  Javascript 社區做了很多努力,在現有的運行環境中,實現"模塊"的效果。本文總結了當前"Javascript 模塊化編程"的最佳實踐,說明如何投入實用。雖然這不是初級教程,但是只要稍稍了解 Javascript 的基本語法,就能看懂。

  一、原始寫法

  模塊就是實現特定功能的一組方法。

  只要把不同的函數(以及記錄狀態的變量)簡單地放在一起,就算是一個模塊。

function m1(){  //...}function m2(){  //...} 

  上面的函數 m1() 和 m2(),組成一個模塊。使用的時候,直接調用就行了。

  這種做法的缺點很明顯:"污染"了全局變量,無法保證不與其他模塊發生變量名沖突,而且模塊成員之間看不出直接關系。

  二、對象寫法

  為了解決上面的缺點,可以把模塊寫成一個對象,所有的模塊成員都放到這個對象里面。

var module1 = new Object ({  _count : 0,  m1 : function (){    //...  },  m2 : function (){    //...  }}); 

  上面的函數 m1()和 m2(),都封裝在 module1 對象里。使用的時候,就是調用這個對象的屬性:

module1.m1(); 

  但是,這樣的寫法會暴露所有模塊成員,內部狀態可以被外部改寫。比如,外部代碼可以直接改變內部計數器的值。

module1._count = 5; 

  三、立即執行函數寫法

  使用"立即執行函數"(Immediately-Invoked Function ExPRession,IIFE),可以達到不暴露私有成員的目的。

var module1 = (function(){  var _count = 0;  var m1 = function(){    //...  };  var m2 = function(){    //...  };  return {  m1 : m1,  m2 : m2  };})(); 

  使用上面的寫法,外部代碼無法讀取內部的_count 變量。

console.info (module1._count); //undefined

  module1就是 Javascript 模塊的基本寫法。下面,再對這種寫法進行加工。

  四、放大模式

  如果一個模塊很大,必須分成幾個部分,或者一個模塊需要繼承另一個模塊,這時就有必要采用"放大模式"(augmentation)。

var module1 = (function (mod){  mod.m3 = function () {    //...  };  return mod;})(module1); 

  上面的代碼為 module1 模塊添加了一個新方法 m3(),然后返回新的 module1 模塊。

  五、寬放大模式(Loose augmentation)

  在瀏覽器環境中,模塊的各個部分通常都是從網上獲取的,有時無法知道哪個部分會先加載。如果采用上一節的寫法,第一個執行的部分有可能加載一個不存在空對象,這時就要采用"寬放大模式"。

var module1 = ( function (mod){  //...  return mod;})(window.module1 {}); 

  與"放大模式"相比,"寬放大模式"就是"立即執行函數"的參數可以是空對象。

  六、輸入全局變量

  獨立性是模塊的重要特點,模塊內部最好不與程序的其他部分直接交互。

  為了在模塊內部調用全局變量,必須顯式地將其他變量輸入模塊。

var module1 = (function ($, YAHOO) {  //...})(jQuery, YAHOO); 

  上面的 module1 模塊需要使用 jQuery 庫和 YUI 庫,就把這兩個庫(其實是兩個模塊)當作參數輸入 module1。這樣做除了保證模塊的獨立性,還使得模塊之間的依賴關系變得明顯。這方面更多的討論,參見 Ben Cherry 的著名文章《JavaScript Module Pattern: In-Depth》。

  七、模塊的規范

  先想一想,為什么模塊很重要?

  因為有了模塊,我們就可以更方便地使用別人的代碼,想要什么功能,就加載什么模塊。

  但是,這樣做有一個前提,那就是大家必須以同樣的方式編寫模塊,否則你有你的寫法,我有我的寫法,豈不是亂了套!考慮到 Javascript 模塊現在還沒有官方規范,這一點就更重要了。

  目前,通行的 Javascript 模塊規范共有兩種:CommonJS 和 AMD。我主要介紹 AMD,但是要先從 CommonJS 講起。

  八、CommonJS

  2009年,美國程序員 Ryan Dahl 創造了 node.js 項目,將 Javascript 語言用于服務器端編程。

  這標志"Javascript 模塊化編程"正式誕生。因為老實說,在瀏覽器環境下,沒有模塊也不是特別大的問題,畢竟網頁程序的復雜性有限;但是在服務器端,一定要有模塊,與操作系統和其他應用程序互動,否則根本沒法編程。

  node.js 的模塊系統,就是參照 CommonJS 規范實現的。在 CommonJS 中,有一個全局性方法 require (),用于加載模塊。假定有一個數學模塊 math.js,就可以像下面這樣加載。

var math = require ('math'); 

  然后,就可以調用模塊提供的方法:

var math = require ('math');math.add (2,3); // 5 

  因為這個系列主要針對瀏覽器編程,不涉及 node.js,所以對 CommonJS 就不多做介紹了。我們在這里只要知道,require () 用于加載模塊就行了。

  九、瀏覽器環境

  有了服務器端模塊以后,很自然地,大家就想要客戶端模塊。而且最好兩者能夠兼容,一個模塊不用修改,在服務器和瀏覽器都可以運行。

  但是,由于一個重大的局限,使得 CommonJS 規范不適用于瀏覽器環境。還是上一節的代碼,如果在瀏覽器中運行,會有一個很大的問題,你能看出來嗎?

var math = require ('math');math.add (2, 3); 

  第二行 Math.add (2, 3),在第一行 require ('math') 之后運行,因此必須等 math.js 加載完成。也就是說,如果加載時間很長,整個應用就會停在那里等。

  這對服務器端不是一個問題,因為所有的模塊都存放在本地硬盤,可以同步加載完成,等待時間就是硬盤的讀取時間。但是,對于瀏覽器,這卻是一個大問題,因為模塊都放在服務器端,等待時間取決于網速的快慢,可能要等很長時間,瀏覽器處于"假死"狀態。

  因此,瀏覽器端的模塊,不能采用"同步加載"(synchronous),只能采用"異步加載"(asynchronous)。這就是 AMD 規范誕生的背景。

  十、AMD

  AMD 是"Asynchronous Module Definition"的縮寫,意思就是"異步模塊定義"。它采用異步方式加載模塊,模塊的加載不影響它后面語句的運行。所有依賴這個模塊的語句,都定義在一個回調函數中,等到加載完成之后,這個回調函數才會運行。

  AMD 也采用 require ()語句加載模塊,但是不同于 CommonJS,它要求兩個參數:

require ([module], callback); 

  第一個參數[module],是一個數組,里面的成員就是要加載的模塊;第二個參數 callback,則是加載成功之后的回調函數。如果將前面的代碼改寫成 AMD 形式,就是下面這樣:

require (['math'], function (math) {    math.add (2, 3);}); 

  math.add () 與 math 模塊加載不是同步的,瀏覽器不會發生假死。所以很顯然,AMD 比較適合瀏覽器環境。

  目前,主要有兩個 Javascript 庫實現了 AMD 規范:require.js 和 curl.js。本系列的第三部分,將通過介紹 require.js,進一步講解 AMD 的用法,以及如何將模塊化編程投入實戰。

  我采用的是一個非常流行的庫 require.js。

  一、為什么要用 require.js?

  最早的時候,所有 Javascript 代碼都寫在一個文件里面,只要加載這一個文件就夠了。后來,代碼越來越多,一個文件不夠了,必須分成多個文件,依次加載。下面的網頁代碼,相信很多人都見過。

<script src="1.js"></script><script src="2.js"></script><script src="3.js"></script><script src="4.js"></script><script src="5.js"></script><script src="6.js"></script>

  這段代碼依次加載多個 js 文件。

  這樣的寫法有很大的缺點。首先,加載的時候,瀏覽器會停止網頁渲染,加載文件越多,網頁失去響應的時間就會越長;其次,由于 js 文件之間存在依賴關系,因此必須嚴格保證加載順序(比如上例的1.js 要在2.js 的前面),依賴性最大的模塊一定要放到最后加載,當依賴關系很復雜的時候,代碼的編寫和維護都會變得困難。

  require.js 的誕生,就是為了解決這兩個問題:

(1)實現 js 文件的異步加載,避免網頁失去響應;

(2)管理模塊之間的依賴性,便于代碼的編寫和維護。

  二、require.js 的加載

  使用 require.js 的第一步,是先去官方網站下載最新版本。

  下載后,假定把它放在 js 子目錄下面,就可以加載了。

<script src="js/require.js"></script>

  有人可能會想到,加載這個文件,也可能造成網頁失去響應。解決辦法有兩個,一個是把它放在網頁底部加載,另一個是寫成下面這樣:

<script src="js/require.js" defer async="true" ></script>

  async 屬性表明這個文件需要異步加載,避免網頁失去響應。IE 不支持這個屬性,只支持 defer,所以把 defer 也寫上。

  加載 require.js 以后,下一步就要加載我們自己的代碼了。假定我們自己的代碼文件是 main.js,也放在 js 目錄下面。那么,只需要寫成下面這樣就行了:

<script src="js/require.js" data-main="js/main"></script>

  data-main 屬性的作用是,指定網頁程序的主模塊。在上例中,就是 js 目錄下面的 main.js,這個文件會第一個被 require.js 加載。由于 require.js 默認的文件后綴名是 js,所以可以把 main.js 簡寫成 main。

  三、主模塊的寫法

  上一節的 main.js,我把它稱為"主模塊",意思是整個網頁的入口代碼。它有點像C語言的 main ()函數,所有代碼都從這兒開始運行。

  下面就來看,怎么寫 main.js。

  如果我們的代碼不依賴任何其他模塊,那么可以直接寫入 javascript 代碼。

// main.jsalert ("加載成功!");

  但這樣的話,就沒必要使用 require.js 了。真正常見的情況是,主模塊依賴于其他模塊,這時就要使用 AMD 規范定義的的 require ()函數。

// main.jsrequire (['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){// some code here});

  require () 函數接受兩個參數。第一個參數是一個數組,表示所依賴的模塊,上例就是['moduleA', 'moduleB', 'moduleC'],即主模塊依賴這三個模塊;第二個參數是一個回調函數,當前面指定的模塊都加載成功后,它將被調用。加載的模塊會以參數形式傳入該函數,從而在回調函數內部就可以使用這些模塊。

  require () 異步加載 moduleA,moduleB 和 moduleC,瀏覽器不會失去響應;它指定的回調函數,只有前面的模塊都加載成功后,才會運行,解決了依賴性的問題。

  下面,我們看一個實際的例子。

  假定主模塊依賴 jquery、underscore 和 backbone 這三個模塊,main.js 就可以這樣寫:

require (['jquery', 'underscore', 'backbone'], function ($, _, Backbone){// some code here});

  require.js 會先加載 jQuery、underscore 和 backbone,然后再運行回調函數。主模塊的代碼就寫在回調函數中。

  四、模塊的加載

  上一節最后的示例中,主模塊的依賴模塊是['jquery', 'underscore', 'backbone']。默認情況下,require.js 假定這三個模塊與 main.js 在同一個目錄,文件名分別為 jquery.js,underscore.js 和 backbone.js,然后自動加載。

  使用 require.config () 方法,我們可以對模塊的加載行為進行自定義。require.config () 就寫在主模塊(main.js)的頭部。參數就是一個對象,這個對象的 paths 屬性指定各個模塊的加載路徑。

require.config ({    paths: {        "jquery": "jquery.min.js",        "underscore": "underscore.min.js",        "backbone": "backbone.min.js"    }});

  上面的代碼給出了三個模塊

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品视频免费在线| 亚洲精品电影网在线观看| 日韩av影院在线观看| 国产综合在线视频| 91精品在线一区| 亚洲二区中文字幕| 欧美老少做受xxxx高潮| 国产精品揄拍一区二区| 91免费国产网站| 日韩av网站在线| 欧美亚洲成人精品| 亚洲人成在线播放| 久久在线免费视频| 不卡av在线播放| 亚洲欧美中文字幕| 日韩精品亚洲精品| 中文字幕久热精品视频在线| 国模gogo一区二区大胆私拍| 韩曰欧美视频免费观看| 欧美在线影院在线视频| 国产成人精品一区| 精品国产91久久久| 91久久精品美女高潮| 亚洲天堂免费观看| 亚洲桃花岛网站| 成人免费视频网址| 日韩电影中文 亚洲精品乱码| 91精品国产99| 国产视频亚洲精品| 亚洲成人精品视频| 国产精品男人的天堂| 久久视频在线直播| 亚洲乱码国产乱码精品精| 国产精品99久久久久久久久久久久| 久久亚洲精品中文字幕冲田杏梨| 久久韩国免费视频| 日韩欧美a级成人黄色| 欧美理论电影网| 亚洲国产精品系列| 色播久久人人爽人人爽人人片视av| 久久久电影免费观看完整版| 国产日韩欧美一二三区| 国内伊人久久久久久网站视频| 亚洲国产成人精品电影| 日本欧美国产在线| 欧美激情图片区| 久久免费少妇高潮久久精品99| www.xxxx精品| 欧美大片大片在线播放| 国产日韩av在线| 午夜欧美不卡精品aaaaa| 日韩国产在线播放| 成人激情视频在线观看| 久久成人免费视频| 国产午夜一区二区| 亚洲一区二区三区乱码aⅴ| 国产v综合v亚洲欧美久久| 欧美成人精品三级在线观看| 97视频在线看| 中文字幕在线亚洲| 久久免费国产精品1| 亚洲性生活视频| 中文字幕亚洲情99在线| 国产精品自拍视频| 日韩视频免费观看| 国产精品久久久久9999| 亚洲电影免费观看| 欧美日韩精品在线| 91在线视频导航| 国产精品国模在线| 日韩中文字幕在线播放| 国产精品黄页免费高清在线观看| 日韩专区在线观看| 国产精品久久久久久网站| 日韩av毛片网| 亚洲黄色www| 1769国内精品视频在线播放| 欧美激情综合亚洲一二区| 亚洲第一页中文字幕| 2019亚洲男人天堂| 国产精品美女久久久久av超清| 日韩精品在线观| 中文字幕综合一区| 亚洲人成自拍网站| 亚洲欧美日韩中文视频| 国产69久久精品成人| 亚洲国产精品yw在线观看| 国产精品免费一区二区三区都可以| 精品久久久久久久久久久久久| 最好看的2019年中文视频| 伊人久久精品视频| 亚洲精品国产美女| 热久久视久久精品18亚洲精品| 国产国语videosex另类| 成人观看高清在线观看免费| 国产精品三级久久久久久电影| 国产91精品久久久久久久| 欧美性视频精品| 国产+成+人+亚洲欧洲| 国产精品美女999| 日韩国产精品亚洲а∨天堂免| 成人网在线视频| 成人国产精品一区二区| 欧美日韩免费在线观看| 日韩中文字幕在线免费观看| 午夜精品三级视频福利| 欧美激情日韩图片| 亚洲欧美日本精品| 在线视频欧美日韩精品| 欧美日韩国产页| 全亚洲最色的网站在线观看| 国产在线拍揄自揄视频不卡99| 91精品国产91久久久久久久久| 国产精品久久久久久久av大片| 国产视频久久久久| 亚洲激情中文字幕| 日韩av在线免费观看| 美女福利精品视频| 中文在线不卡视频| 国产主播在线一区| 日韩高清欧美高清| 国产www精品| 成人春色激情网| 国产精品亚洲аv天堂网| 91九色国产社区在线观看| 在线中文字幕日韩| 一本色道久久综合狠狠躁篇怎么玩| 日本伊人精品一区二区三区介绍| 亚洲福利影片在线| 午夜精品福利在线观看| 欧美猛交ⅹxxx乱大交视频| 95av在线视频| 日本中文字幕不卡免费| 成人精品视频在线| 中文字幕无线精品亚洲乱码一区| 九九综合九九综合| 国产视频在线一区二区| 国产精品网站大全| 国产999精品久久久影片官网| 日韩在线视频观看正片免费网站| 国产日韩欧美在线观看| 亚洲精品日韩激情在线电影| 青草成人免费视频| 亚洲日韩中文字幕| 欧美一级视频在线观看| 中文字幕欧美日韩| 欧美黄色片免费观看| 欧美综合在线第二页| 欧美精品video| 91精品国产高清久久久久久| 亚洲女人被黑人巨大进入| 久久精品国产96久久久香蕉| 日韩欧美精品免费在线| 亚洲一区二区三区乱码aⅴ| 日韩精品在线观看网站| 亚洲国产精品大全| 亚洲欧洲日产国码av系列天堂| 国产欧美日韩中文字幕在线| 91久久精品美女高潮| 国产欧美日韩中文字幕在线| 91视频-88av| 亚洲精品suv精品一区二区| 精品国产鲁一鲁一区二区张丽| 91av在线视频观看|