一朝群、 模塊規(guī)范
一句話總結(jié):CommonJs用于服務(wù)端Node.js中姜盈,AMD和CMD是針對(duì)客戶端的規(guī)范哭当,為了不讓引入依賴阻塞了代碼進(jìn)行猪腕,使用了異步加載模塊。
1. CommonJs:
- 適用區(qū)域:用于服務(wù)端钦勘。
- 導(dǎo)入:
require
- 導(dǎo)出:
module.exports
陋葡,exports
。 - exports與module.exports
exports
是module.exports
的引用彻采,var exports = module.exports = {};
腐缤,而最終導(dǎo)出的是仍然是module.exports
,因此肛响,倘若更改exports
的指向岭粤,最終返回的仍然是module.exports
。 - 用法:
module.exports 基礎(chǔ)用法
/* export.js */
const a = 1
module.exports = a
/* import.js */
var a = require('./export')
// a = 1
exports 基礎(chǔ)用法
/* export.js */
exports.a = 1 // 不能改變引用, exports = {a:1}??
/* import.js */
var a = require('./export')
// a = {a:1}
可以使用es6的特性 - 解構(gòu)賦值
/* export.js */
exports.a = 1
/* import.js */
var {a} = require('./export')
// a = 1
- 為什么不適用于客戶端特笋?
同步引用不適用于客戶端場(chǎng)景
var _ = require('./loadsh')
_.map([1,2,3], square)
如上面??所示剃浇,如果loadsh這個(gè)庫由于網(wǎng)絡(luò)原因加載得很慢的話,那么它便阻塞了后面代碼的運(yùn)行猎物,這樣對(duì)用戶體驗(yàn)犧牲很大虎囚。
這時(shí)候AMD就有了誕生的需求了。
2. AMD:
AMD是”Asynchronous Module Definition”的縮寫蔫磨,意思就是”異步模塊定義”淘讥。它采用異步方式加載模塊,模塊的加載不影響它后面語句的運(yùn)行堤如。所有依賴這個(gè)模塊的語句蒲列,都定義在一個(gè)回調(diào)函數(shù)中,等到加載完成之后煤惩,這個(gè)回調(diào)函數(shù)才會(huì)運(yùn)行嫉嘀。
- 使用define定義模塊:
// id:模塊名(可選),dependencies:依賴庫(可選),factory工廠方法,返回一個(gè)模版函數(shù)
define(id?, [dependencies?], factory)
// demo
define(['Lib'], function(Lib){
function foo(){
Lib.doSomething();
}
return {
foo : foo
};
});
- 使用require加載模塊,因?yàn)槭腔卣{(diào)執(zhí)行魄揉,所以不阻塞啦剪侮。
// module:加載的模塊數(shù)組, callback:加載成功后再執(zhí)行的回調(diào)函數(shù)
require([module], callback);
// demo
require([loadsh], loadsh.map([1,2,3],square))
目前,主要有兩個(gè)Javascript庫實(shí)現(xiàn)了AMD規(guī)范:require.js和curl.js。
3. CMD:
CMD (Common Module Definition), 是seajs推崇的規(guī)范瓣俯。它與AMD最大的區(qū)別是它推崇依賴就近杰标。
- 同樣,CMD使用define定義模塊
// id:模塊名(可選),dependencies:依賴庫(可選),factory工廠方法,返回一個(gè)模版函數(shù)
define(id?, [dependencies?], factory)
// 不同點(diǎn):它可以在工廠函數(shù)中導(dǎo)出導(dǎo)入(也是通常的做法)彩匕,也是它推崇的導(dǎo)出導(dǎo)入方式
define(function(require, exports, module) {
// 模塊代碼
var $ = require('jquery.js')
$('div').addClass('active');
});
- 用use加載模塊
// 加載模塊
seajs.use(['myModule.js'], function(my){
});
- 與AMD的區(qū)別:
最明顯的區(qū)別就是在模塊定義時(shí)對(duì)依賴的處理不同
1腔剂、AMD推崇依賴前置,在定義模塊的時(shí)候就要聲明其依賴的模塊
2驼仪、CMD推崇就近依賴掸犬,只有在用到某個(gè)模塊的時(shí)候再去require
這種區(qū)別各有優(yōu)劣,只是語法上的差距绪爸,而且requireJS和SeaJS都支持對(duì)方的寫法
AMD和CMD最大的區(qū)別是對(duì)依賴模塊的執(zhí)行時(shí)機(jī)處理不同湾碎,注意不是加載的時(shí)機(jī)或者方式不同。
AMD在加載模塊完成后就會(huì)執(zhí)行改模塊奠货,所有模塊都加載執(zhí)行完后會(huì)進(jìn)入require的回調(diào)函數(shù)介褥,執(zhí)行主邏輯,這樣的效果就是依賴模塊的執(zhí)行順序和書寫順序不一定一致递惋,看網(wǎng)絡(luò)速度柔滔,哪個(gè)先下載下來,哪個(gè)先執(zhí)行萍虽,但是主邏輯一定在所有依賴加載完成后才執(zhí)行
CMD加載完某個(gè)依賴模塊后并不執(zhí)行睛廊,只是下載而已,在所有依賴模塊加載完成后進(jìn)入主邏輯贩挣,遇到require語句的時(shí)候才執(zhí)行對(duì)應(yīng)的模塊喉前,這樣模塊的執(zhí)行順序和書寫順序是完全一致的
二. ES6
這里主要介紹:
- ES6的import和export和export default的基本用法
- ES6和CommonJs的混用
1. 基本用法
/* export.js */
export const a = 1
/* import.js */
import { a } from './export'
// a = 1
經(jīng)過babel的轉(zhuǎn)換⊥醪疲可以看到轉(zhuǎn)化為exports->require,并且給exports添加了一個(gè)__esModule的屬性裕便。
/* export.js */
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.a = void 0;
const a = 1;
exports.a = a;
/* import.js */
"use strict";
var _export = require("./export");
console.log(_export.a);
export default
// export.js
const b = 2
export default b
// import.js
import b from './export'
console.log(b)
通過babel轉(zhuǎn)化绒净,使用exports.default進(jìn)行導(dǎo)出。
/* export.js */
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
const b = 2;
var _default = b;
exports.default = _default;
??注意:不能認(rèn)為 import { b } from './export'
是用了解構(gòu)賦值偿衰。當(dāng)執(zhí)行以下代碼是不行的挂疆。import 語句中的"解構(gòu)賦值"并不是解構(gòu)賦值,而是 named imports下翎。
// import.js
import { {a} } from './export' // 語法錯(cuò)誤
console.log(a)
// export.js
export const b = { a: 1 }
named imports
缤言,語法上和解構(gòu)賦值很像,但還是有所差別视事,比如下面的例子胆萧。
import { b as a } from './export' // 解構(gòu)賦值中不能用 as
因此還是得老老實(shí)實(shí)把值接下來,然后再去處理〉耄或者你可以和CommonJs混用來達(dá)到類似解構(gòu)賦值的效果订晌。
2. 與CommonJs混用
由于babel解析的時(shí)候也是解析成exports->require形式的,因此可以和commonJs混用蚌吸。
- import.js / require - export.js / export
// import.js
var { b } = require('./export').default
console.log(b)
// export.js
export default {
b: 2
}
- import.js / import - export.js / exports
// import.js
import { a } from './export'
console.log(a)
// export.js
module.exports = {
a: 1
}