首先區(qū)分CommonJS 和 ES6.
一、為了便于模塊化開發(fā)糊探,在ES5 中 提供了AMD ,CMD,CommonJS 這三種主流的模塊化方案,然后ES6 中 增加了import/export;
1河闰、AMD 是RequireJS推廣中對(duì)模塊定義的規(guī)范化產(chǎn)出科平,它是一個(gè)概念,RequireJS是對(duì)這個(gè)概念的實(shí)現(xiàn)姜性,就好比JavaScript語言是對(duì)ECMAScript規(guī)范的實(shí)現(xiàn)
RequireJS:是一個(gè)AMD框架瞪慧,可以異步加載JS文件,按照模塊加載方法部念,通過define()函數(shù)定義弃酌,第一個(gè)參數(shù)是一個(gè)數(shù)組,里面定義一些需要依賴的包儡炼,第二個(gè)參數(shù)是一個(gè)回調(diào)函數(shù)妓湘,通過變量來引用模塊里面的方法,最后通過return來輸出乌询。 是一個(gè)依賴前置榜贴、異步定義的AMD框架(在參數(shù)里面引入js文件),在定義的同時(shí)如果需要用到別的模塊妹田,在最前面定義好即在參數(shù)數(shù)組里面進(jìn)行引入唬党,在回調(diào)里面加載
2鹃共、CMD 是SeaJS在推廣過程中對(duì)模塊定義的規(guī)范化產(chǎn)出,是一個(gè)同步模塊定義初嘹,是SeaJS的一個(gè)標(biāo)準(zhǔn)及汉,SeaJS是CMD概念的一個(gè)實(shí)現(xiàn),
SeaJS是淘寶團(tuán)隊(duì)提供的一個(gè)模塊開發(fā)的js框架.通過define()定義屯烦,沒有依賴前置坷随,通過require加載jQuery插件,CMD是依賴就近驻龟,在什么地方使用到插件就在什么地方require該插件温眉,即用即返,這是一個(gè)同步的概念
3翁狐、CommonJS 規(guī)范---是通過module.exports定義的类溢,在前端瀏覽器里面并不支持module.exports,通過node.js后端使用的。Nodejs端是使用CommonJS規(guī)范的露懒,前端瀏覽器一般使用AMD闯冷、CMD、ES6等定義模塊化開發(fā)的
服務(wù)端使用懈词,不支持瀏覽器端蛇耀;輸出方式有2種:默認(rèn)輸出---module export 和帶有名字的輸出---exports.area
4、ES6 特性坎弯,模塊化---export/import對(duì)模塊進(jìn)行導(dǎo)出導(dǎo)入的
5纺涤、UMD嚴(yán)格上說,umd不能算是一種模塊規(guī)范抠忘,因?yàn)樗鼪]有模塊定義和調(diào)用撩炊,這是AMD和CommonJS(服務(wù)端模塊化規(guī)范)的結(jié)合體,保證模塊可以被amd和commonjs調(diào)用崎脉。
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['b'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require('b'));
} else {
// Browser globals (root is window)
root.returnExports = factory(root.b);
}
}(this, function (b) {
//use b in some fashion.
// Just return a value to define the module export.
// This example returns an object, but the module
// can return a function as the exported value.
return {}
}));
AMD 與CMD 區(qū)別
1拧咳、AMD推崇依賴前置,在定義模塊的時(shí)候就要聲明其依賴的模塊
2囚灼、CMD推崇就近依賴呛踊,只有在用到某個(gè)模塊的時(shí)候再去require
這種區(qū)別各有優(yōu)劣,只是語法上的差距啦撮,而且requireJS和SeaJS都支持對(duì)方的寫法
AMD和CMD最大的區(qū)別是對(duì)依賴模塊的執(zhí)行時(shí)機(jī)處理不同谭网,注意不是加載的時(shí)機(jī)或者方式不同
很多人說requireJS是異步加載模塊,SeaJS是同步加載模塊赃春,這么理解實(shí)際上是不準(zhǔn)確的愉择,其實(shí)加載模塊都是異步的,只不過AMD依賴前置,js可以方便知道依賴模塊是誰锥涕,立即加載衷戈,而CMD就近依賴,需要使用把模塊變?yōu)樽址馕鲆槐椴胖酪蕾嚵四切┠K层坠,這也是很多人詬病CMD的一點(diǎn)殖妇,犧牲性能來帶來開發(fā)的便利性,實(shí)際上解析模塊用的時(shí)間短到可以忽略
為什么我們說兩個(gè)的區(qū)別是依賴模塊執(zhí)行時(shí)機(jī)不同破花,為什么很多人認(rèn)為ADM是異步的谦趣,CMD是同步的(除了名字的原因。座每。前鹅。)
同樣都是異步加載模塊,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í)行順序和書寫順序是完全一致的
這也是很多人說AMD用戶體驗(yàn)好馆衔,因?yàn)闆]有延遲贡歧,依賴模塊提前執(zhí)行了,CMD性能好探膊,因?yàn)橹挥杏脩粜枰臅r(shí)候才執(zhí)行的原因
二杠愧、Node應(yīng)用由模塊組成,采用CommonJS模塊規(guī)范
根據(jù)這個(gè)規(guī)范逞壁,每個(gè)文件就是一個(gè)模塊流济,有自己的作用域。在一個(gè)文件里面定義的變量腌闯、函數(shù)绳瘟、類,都是私有的姿骏,對(duì)其他文件不可見糖声。
CommonJS規(guī)范規(guī)定,每個(gè)模塊內(nèi)部,module變量代表當(dāng)前模塊蘸泻。這個(gè)變量是一個(gè)對(duì)象琉苇,它的exports屬性(即module.exports)是對(duì)外的接口。加載某個(gè)模塊悦施,其實(shí)是加載該模塊的module.exports屬性并扇。
為了方便,Node為每個(gè)模塊提供一個(gè)exports變量抡诞,指向module.exports
//utils.js
let a = 100;
console.log(module.exports); //能打印出結(jié)果為:{}
console.log(exports); //能打印出結(jié)果為:{}
exports.a = 200; //這里辛苦勞作幫 module.exports 的內(nèi)容給改成 {a : 200}
exports = '指向其他內(nèi)存區(qū)'; //這里把exports的指向指走
//test.js
var a = require('/utils');
console.log(a) // 打印為 {a : 200}復(fù)制代碼
所有就是說如果修改exports 其實(shí)修改了模塊中的一個(gè)exports變量穷蛹,但是由于修改后不再指向module.exports了。就不會(huì)被導(dǎo)出了沐绒。
三俩莽、ES6使用 export 和 import 來導(dǎo)出、導(dǎo)入模塊乔遮。
export 和 export default扮超,還有 導(dǎo)入的時(shí)候,import a from ..,import {a} from ..蹋肮,總之也有點(diǎn)亂出刷,那么下面我們就開始把它們捋清楚吧
export命令規(guī)定的是對(duì)外的接口,必須與模塊內(nèi)部的變量建立一一對(duì)應(yīng)關(guān)系
export default命令坯辩,為模塊指定默認(rèn)輸出
- export與export default均可用于導(dǎo)出常量馁龟、函數(shù)、文件漆魔、模塊等
- 在一個(gè)文件或模塊中坷檩,export、import可以有多個(gè)改抡,export default僅有一個(gè)
- 通過export方式導(dǎo)出矢炼,在導(dǎo)入時(shí)要加{ },export default則不需要
- export能直接導(dǎo)出變量表達(dá)式阿纤,export default不行句灌。
testEs6Export.js
'use strict'
//導(dǎo)出變量
export const a = '100';
//導(dǎo)出方法
export const dogSay = function(){
console.log('wang wang');
}
//導(dǎo)出方法第二種
function catSay(){
console.log('miao miao');
}
export { catSay };
//export default導(dǎo)出
const m = 100;
export default m;
//export defult const m = 100;// 這里不能寫這種格式。復(fù)制代碼
index.js
//index.js
'use strict'
import { dogSay, catSay } from './testEs6Export'; //導(dǎo)出了 export 方法
import m from './testEs6Export'; //導(dǎo)出了 export default
import * as testModule from './testEs6Export';//as 集合成對(duì)象導(dǎo)出
console.log('11111', dogSay, catSay); // ? dogSay() { console.log('wang ang'); }? catSay() { console.log('miao miao');}
console.log('2222', m);//100
console.log('3333', testModule);// Module :{a:"100",catSay:f catSay(),default:100,dogSay: f dogSay()}
console.log('3333', testModule.a); // "100"
console.log('4444', testModule.m); // undefined 因?yàn)? as 導(dǎo)出是 把 零散的 export 聚集在一起作為一個(gè)對(duì)象欠拾,而export default 是導(dǎo)出為 default屬性胰锌。
console.log('5555', testModule.default); // 100
參考:
https://blog.csdn.net/weixin_42966484/article/details/82889608
https://blog.csdn.net/qq_31967569/article/details/82461499
https://blog.csdn.net/tangxiujiang/article/details/81104174
https://www.cnblogs.com/fayin/p/6831071.html
https://zhuanlan.zhihu.com/p/75980415