開發者能夠只須要實現業務邏輯,其餘可加載別人寫好的公共模塊。javascript
script
引入文件<script src="jquery.js"></script>
<script src="jquery_scroller.js"></script>
<script src="bootstarp.js"></script>
<script src="commutil.js"></script>
<script src="main.js"></script>
複製代碼
/** commutil.js(main.js)中: 模塊就是實現特定功能的一組方法。 只要把不一樣的函數簡單地放在一塊兒,就算是一個模塊。 */
function fun1(){
...
}
function fun2(){
...
}
...
複製代碼
缺點:前端
jquery
, 那麼 jquery
就必定要先加載,var obj = new Object({
_count : 0,
fun1 : function (){
...
},
fun2 : function (){
...
}
});
複製代碼
//調用方法
obj.fun1()
obj.fun2()
複製代碼
缺點:java
obj._count = 1;
複製代碼
使用」當即執行函數」(Immediately-Invoked Function Expression,IIFE
),能夠達到不暴露私有成員的目的。node
var obj = (function() {
var _count = 0;
var fun1 = function() {
alert(_count)
}
var fun2 = function() {
alert(_count + 1)
}
return {
fun1, fun2
}
})()
複製代碼
使用上面的寫法,外部代碼沒法讀取內部的_count變量。jquery
console.info(obj._count); //undefined
//調用內部函數能夠
obj.fun1()
複製代碼
jQuery
用的就是當即執行函數。require
導入模塊【運行時加載】隨着web
項目愈來愈大,JS
的代碼量也與日俱增,因而社區就自發約定了幾種模塊化的方案:requirejs
遵循AMD
,seajs
遵循CMD
,node
的module
遵循CommonJS
規範,雖然寫法上有所不一樣,都是爲了可以間接實現模塊化的基礎上保持較爲一致的代碼風格。程序員
Ryan Dahl
創造了node.js
項目,將javascript
語言用於服務器端編程。 這標誌「Javascript模塊化編程」正式誕生。node
編程最重要的思想之一就是模塊,正是這個思想,讓JavaScript
的大規模工程成爲可能。js
界流行,也是基於此,隨後在瀏覽器端,requirejs
和seajs
之類的工具包也出現了。require
統治了ES6
以前的全部模塊化編程,即便如今,在ES6 module
被徹底實現以前,仍是這樣。一個文件就是一個模塊, 其內部定義的變量, 方法都處於該模塊內, 不會對外暴露.es6
//新建 a.js, 導出sayHello和introSelf
// a.js
function sayHello(name) {
console.log(`Hello ${name}`)
}
function introSelf(name, age){
var msg = "myName is " + name + " and I'm " + age + " old";
console.log(msg);
}
module.exports.sayHello = sayHello
module.exports.introSelf = introSelf
/**或 module.exports = { sayHello: sayHello, introSelf: introSelf } */
//在 b.js 中引入 a 並調用
// b.js
const a = require('./a')
a.sayHello('Lucy')
a.introSelf('Lucy', 20)
複製代碼
CommonJs
是同步加載的模塊的, 在服務端(node
), 文件都在硬盤上, 因此同步加載也無所謂, 可是在瀏覽器端, 同步加載就體驗很差了. 因此 CommonJs
主要使用於 node
環境下.synchronous
),只能採用」異步加載」(asynchronous
)。這就是AMD
規範誕生的背景。AMD
是Asynchronous Module Definition
的縮寫,意思就是」異步模塊定義」。它採用異步方式加載模塊,模塊的加載不影響它後面語句的運行。全部依賴這個模塊的語句,都定義在一個回調函數中,等到加載完成以後,這個回調函數纔會運行。CMD (Common Module Definition)
,阿里的玉伯提出, 是seajs推崇的規範,CMD
則是依賴就近,用的時候再require
(實現了按需加載)。 模塊必須採用特定的define()
函數來定義。AMD
和CMD
模塊必須採用特定的define()函數來定義。define(id?, dependencies?, factory)
/** - id:字符串,模塊名稱(可選) - dependencies: 是咱們要載入的依賴模塊(可選), 使用相對路徑。,注意是數組格式 - factory: 工廠方法,返回一個模塊函數 */
複製代碼
若是一個模塊不依賴其餘模塊,那麼能夠直接定義在define()函數之中。web
AMD
推崇依賴前置(js能夠方便知道依賴模塊是誰,當即加載),而 CMD
推崇依賴就近(須要使用把模塊變爲字符串解析一遍才知道依賴了那些模塊,這也是不少人詬病CMD
的一點)//AMD2.0以前
require(['./a', './b'], function(a, b) {
a.doSomething();
b.doSomething();
})
// AMD2.0以後
define(['./a', './b'], function(a, b) {
a.doSomething();
b.doSomething();
})
// CMD
define(function(require, exports, module) {
var a = require('./a');
a.doSomething();
var b = require('./b');
b.doSomething();
})
複製代碼
require([module], callback);
複製代碼
//若有一個math.js
require(['math'], function (math) {
math.add(2, 3);
});
複製代碼
ES6 MODULES
【編譯時加載】隨着ES2015
的發佈,官方標準定義了一種模塊化的方案,那就是import
、export
。但是,標準畢竟是標準,各大瀏覽器和node終端要實現標準仍是有一段距離的。編程
export
和import
。export
命令用於規定模塊的對外接口,import
命令用於輸入其餘模塊提供的功能。export
關鍵字輸出該變量。下面是一個 JS
文件,裏面使用export
命令輸出變量。// profile.js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
複製代碼
profile.js
文件,保存了用戶信息。ES6
將其視爲一個模塊,裏面用export命令對外部輸出了三個變量。export
的寫法,除了像上面這樣,還有另一種。// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export { firstName, lastName, year };
複製代碼
import { firstName, lastName, year } from './profile.js';
//也能夠用as
import { lastName as surname } from './profile.js';
複製代碼
export
命令後面,使用大括號指定所要輸出的一組變量。它與前一種寫法(直接放置在var
語句前)是等價的,可是應該優先考慮使用這種寫法。由於這樣就能夠在腳本尾部,一眼看清楚輸出了哪些變量。export
命令除了輸出變量,還能夠輸出函數或類(class
)。export function multiply(x, y) {
return x * y;
};
複製代碼
multiply
。export
輸出的變量就是原本的名字,可是可使用as
關鍵字重命名。function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2,
v2 as streamLatestVersion
};
複製代碼
as
關鍵字,重命名了函數v1
和v2
的對外接口。重命名後,v2
能夠用不一樣的名字輸出兩次。export
命令規定的是對外的接口,必須與模塊內部的變量創建一一對應關係。// 報錯
export 1;
// 報錯
var m = 1;
export m;
複製代碼
// 寫法一
export var m = 1;
// 寫法二
var m = 1;
export {m};
// 寫法三
var n = 1;
export {n as m};
複製代碼
function
和class
的輸出,也必須遵照這樣的寫法。// 報錯
function f() {}
export f;
// 正確
export function f() {};
// 正確
function f() {}
export {f};
複製代碼
import
命令的時候,用戶須要知道所要加載的變量名或函數名,不然沒法加載。可是,用戶確定但願快速上手,未必願意閱讀文檔,去了解模塊有哪些屬性和方法。export default
命令,爲模塊指定默認輸出。// export-default.js
export default function () {
console.log('foo');
}
複製代碼
export-default.js
,它的默認輸出是一個函數。import
命令能夠爲該匿名函數指定任意名字。// import-default.js
import customName from './export-default';
customName(); // 'foo'
複製代碼
import
命令,能夠用任意名稱指向export-default.js
輸出的方法,這時就不須要知道原模塊輸出的函數名。須要注意的是,這時import
命令後面,不使用大括號。export default
命令用在非匿名函數前,也是能夠的。// export-default.js
export default function foo() {
console.log('foo');
}
// 或者寫成
function foo() {
console.log('foo');
}
export default foo;
複製代碼
foo
函數的函數名foo
,在模塊外部是無效的。加載的時候,視同匿名函數加載。