第一章 JavaScript模塊化編程javascript
(一):模塊的寫法php
一 原始寫法
// 模塊就是實現特定功能的一組方法;只要把不一樣的函數(以及記錄狀態的變量)簡單地放在一塊兒,就算是一個模塊;
function m1(){
// ...
}
function m2(){
// ...
}
// 上面的函數m1()和m2(),組成一個模塊;使用時直接調用就行;
// 缺點:"污染"了全局變量; 沒法保證不與其餘模塊發生變量名衝突,並且模塊成員之間看不出直接關係;java
二 對象寫法node
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;
|
三 當即執行函數寫法jquery
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模塊的基本寫法;
|
四 放大模式ajax
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 || {});
// 與"放大模式"相比,"寬放大模式"就是"當即執行函數"的參數能夠是空對象;
|
六 輸入全局變量api
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",
"backbone":"backbone.min"
}
});
// 若是加載的模塊和主模塊不在同一個目錄,就要逐一指定路徑;
require.config({
paths:{
"jquery":"lib/jquery.min",
"underscore":"lib/underscore.min",
"backbone":"lib/backbone.min"
}
});
// 或者直接改變基目錄(baseUrl)
require.config({
baseUrl:"js/lib",
paths:{
"jquery":"jquery.min",
"underscore":"underscore.min",
"backbone":"backbone.min"
}
});
// 若是模塊在另外一臺主機上,也能夠直接指定它的網址
require.config({
paths:{
"jquery":"https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"
}
});
// require.js要求,每一個模塊是一個單獨的js文件;這樣的話,若是加載多個模塊,就會發出屢次HTTP請求,會影響網頁的加載速度;
// 所以,require.js提供了一個優化工具,當模塊部署完畢之後,能夠用這個工具將多個模塊合併在一個文件中,減小HTTP請求數;
五 AMD模塊的寫法
// require.js加載的模塊,採用AMD規範,也就是說,模塊必須按照AMD的規定來寫;
// 具體來講,就是模塊必須採用特定的define()函數來定義;若是一個模塊不依賴其餘模塊,那麼能夠直接定義在define()函數中;
// 在math.js中定義math模塊
// math.js
define(function(){
var add = function(x,y){
return x+y;
};
return {
add:add
};
});
// 在main.js中加載math模塊
require(['math'],function(math){
alert(math.add(1,1));
});
// 若是這個模塊還依賴其餘模塊,那麼define()函數的第一個參數,必須是一個數組,指明該模塊的依賴性;
// math.js
define(['myLib'],function(myLib){
function foo(){
myLib.doSomething();
}
return {
foo:foo
};
});
// 當require()函數加載上面這個模塊的時候,就會先加載myLib.js文件;
六 加載非規範的模塊
// 加載非規範的模塊,在用require()加載以前,要先用require.config()方法,定義它們的一些特徵;
require.config({
shim:{
'underscore':{
exports:'_'
},
'backbone':{
deps:['underscore','jquery'],
exports:'Backbone'
}
}
});
// require.config()接收一個配置對象,這個對象除了有前面說過的paths屬性以外,還有一個shim屬性,專門用來配置不兼容的模塊;
// (1).定義deps數組,代表該模塊的依賴性;
// (2).定義exports值(輸出的變量名),代表這個模塊外部調用時的名稱;
好比:jQuery的插件
shim:{
'jquery.scroll':{
deps:['jquery'],
exports:'jQuery.fn.scroll'
}
};
七 require.js插件
1.domready:可讓回調函數在頁面DOM結構加載完成以後運行; require(['domready!'],function(doc){ // called once the DOM is ready; }) 2.text和image:容許require.js加載文本和圖片文件; define(['text!review.txt','image!cat.jpg'],function(review,cat){ console.log(review); document.body.appendChild(cat); });