一直對JS都是一知半解,最近遇到這方面問題,所以在網上學習了一下,現在還沒有完全明白,先貼出筆記;
第一章 JavaScript模塊化編程
(一):模塊的寫法
一 原始寫法
// 模塊就是實現特定功能的一組方法;只要把不同的函數(以及記錄狀態的變量)簡單地放在一起,就算是一個模塊;
function m1(){
// ...
}
function m2(){
// ...
}
// 上面的函數m1()和m2(),組成一個模塊;使用時直接調用就行;
// 缺點:"污染"了全局變量; 無法保證不與其他模塊發生變量名沖突,而且模塊成員之間看不出直接關系;
二 對象寫法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // 把模塊寫成一個對象,所有的模塊成員都放到這個對象裡面; var module = new Object({ _count:0, m1:function(){ // ... }, m2:function(){ // ... } }); // 上面的函數m1()和m2(),都封裝在module對象裡;使用時直接調用這個對象的屬性; module.m1(); // 但是,這樣的寫法會暴露所有模塊成員,內部狀態可以被外部改寫; module._count = 4;三 立即執行函數寫法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 var module = (function(){ var _count = 0; var m1 = function(){ // ... }; var m2 = function(){ }; return { m1:m1, m2:m2 }; })(); // 使用上面的寫法,外部代碼無法讀取內部的_count變量; console.info(module._count); // undefined; // 上面的寫法就是JavaScript模塊的基本寫法;四 放大模式
1 2 3 4 5 6 7 8 // 如果模塊很大,必須分成幾個部分,或者一個模塊需要繼承另一個模塊,這時就有必要采用"放大模式"; var module = (function(mod){ mod.m3 = function(){ // ... }; return mod; })(module); // 上面的代碼為module模塊添加了一個新方法m3(),然後返回新的module模塊;五 寬放大模式
1 2 3 4 5 6 7 // 在浏覽器環境中,模塊的各個部分通常都是從網上獲取的,有時無法知道哪個部分會先加載; // 如果采用上一節的寫法,第一個執行的部分有可能加載一個不存在的空對象,這時就要采用"寬放大模式"; var module = (function(mod){ // ... return mod; })(window.module || {}); // 與"放大模式"相比,"寬放大模式"就是"立即執行函數"的參數可以是空對象;六 輸入全局變量
1 2 3 4 5 6 7 // 獨立性是模塊的重要特點,模塊內部最好不與程序的其他部分直接交互; // 為了在模塊內部調用全局變量,必須顯式地將其他變量輸入模塊; var module = (function($,YAHOO){ // ... })(jQuery,YAHOO); // 上面的module模塊需要使用jQuery庫和YUI庫,就把這兩個庫(其實是兩個模塊)當作參數輸入module; // 這樣做除了保證模塊的獨立性,還使得模塊之間的依賴關系變得明顯;第二章 JavaScript模塊化編程(二):AMD規范
一 模塊的規范
// 目前,通行的JavaScript模塊規范共有兩種:CommonJS和AMD;
二 CommonJS
// node.js將javascript語言用於服務器端編程,這標志"JavaScript模塊化編程"正式誕生;
// node.js的模塊系統,就是參照CommonJS規范實現的;
在CommonJS中,有一個全局性方法require(),用於加載模塊;
var math = require('math'); // 加載模塊;
math.add(2,3); // 調用模塊方法=>5;
三 浏覽器環境
// 上一節的代碼在浏覽器中運行會有很大的問題;
var math = require('math');
math.add(2,3);
// 問題:必須在require('math')等math.js加載完成,才會執行math.add(2,3);
// 所以浏覽器的模塊,不能采用"同步加載",只能采用"異步加載";==>AMD;
四 AMD
AMD(Asynchronous Module Definition)異步模塊定義;
// 采用異步加載模塊,模塊的加載不影響它後面語句的運行,所有依賴這個模塊的語句,都定義在一個回調函數中,
// 等加載完成之後,這個回調函數才會運行;
// AMD也采用require()語句加載模塊,但是它要求兩個參數:
require([module],callback);
// module:是一個數組,裡面的成員就是要加載的模塊;
// callback:是加載成功之後的回調函數;
require(['math'],function(math){
math.add(2,3);
});
// math.add()與math模塊加載不是同步的,浏覽器不會發生假死;所以,AMD比較適合浏覽器環境;
第三章 JavaScript模塊化編程(三):require.js的用法
一 為什麼使用require.js
// 需要依次加載多個js文件;
// 缺點:
// 1.加載的時候,浏覽器會停止網頁渲染,加載文件越多,網頁失去響應的時間就會越長;
// 2.由於js文件之間存在依賴關系,因此必須嚴格保證加載順序,當依賴關系很復雜的時候,代碼的編寫和維護都會變得困難;
// 所以require.js解決了這兩個問題:
// 1.實現js文件的異步加載,避免網頁失去響應;
// 2.管理模塊之間的依賴性,便於代碼的編寫和維護;
二 require.js的加載
1.加載require.js
<script scr="js/require.js" defer async="true"></script>
// async屬性表明這個文件需要異步加載,避免網頁失去響應;IE不支持這個屬性,只支持defer,所以把defer也寫上;
2.加載main.js
<script src="js/require.js" data-main="js/main"></script>
// data-main屬性的作用是,指定網頁程序的主模塊=>main.js,這個文件會第一個被require.js加載;
// 由於require.js默認的文件後綴名是js,所以可以把main.js簡寫成main;
三 主模塊main.js的寫法
1.如果main.js不依賴任何其他模塊,可以直接寫入JavaScript代碼;
// main.js
alert('加載成功!');
2.如果main.js依賴於模塊,這時就要使用AMD規范定義的require()函數;
// main.js
require(['moduleA','moduleB','moduleC'],function(moduleA,moduleB,moduleC){
// ...
})
// require()函數接收兩個參數:
// 參數一:數組,表示所依賴的模塊,即主模塊依賴的三個模塊;
// 參數二:回調函數,當前面指定的模塊都加載成功後,它將被調用;加載的模塊會以參數形式傳入該函數,從而在回調函數內部可以使用這些模塊;
// require()異步加載模塊,浏覽器不會失去響應;它指定的回調函數,只有前面的模塊都加載成功後,才會運行,解決了依賴性的問題;
實例:
require(['jquery','underscore','backbone'],function($,_,Backbone){
// ...
});
四 模塊的加載
// 使用require.config()方法,可以對模塊的加載行為進行自定義;
// require.config()就寫在主模塊(main.js)的頭部;
// 參數就是一個對象,這個對象的paths屬性指定各個模塊的加載路徑;
// 設定以下三個模塊的文件默認和main.js在用一個目錄;
require.config({
paths:{
"jquery":"jquery.min",
"underscore":"underscore.min&qu