javascript
CommonJS/AMD/CMD/UMD
為什么會(huì)有這幾種模式?
起源:Javascript模塊化
模塊化就是把復(fù)雜問題分解成不同模塊,這樣可維護(hù)性高,從而達(dá)到高復(fù)用,低耦合。
1.Commonjs
CommonJS是服務(wù)器端模塊的規(guī)范,Node.js采用了這個(gè)規(guī)范
根據(jù)CommonJS規(guī)范,一個(gè)單獨(dú)的文件就是一個(gè)模塊。加載模塊使用require方法,該方法讀取一個(gè)文件并執(zhí)行,最后返回文件內(nèi)部的exports對(duì)象。
// foobar.js
?
//私有變量
var test = 123;
?
//公有方法
function foobar () {
?
? ? this.foo = function () {
? ? ? ? // do someing ...
? ? }
? ? this.bar = function () {
? ? ? ? //do someing ...
? ? }
}
?//exports對(duì)象上的方法和變量是公有的
var foobar = new foobar();
exports.foobar = foobar;
?
//require方法默認(rèn)讀取js文件,所以可以省略js后綴
var test = require('./boobar').foobar;
test.bar();
2.AMD和RequireJS
AMD是"Asynchronous Module Definition"的縮寫,意思就是"異步模塊定義".
AMD設(shè)計(jì)出一個(gè)簡(jiǎn)潔的寫模塊API:
define(id?, dependencies?, factory);
第一個(gè)參數(shù) id 為字符串類型,表示了模塊標(biāo)識(shí),為可選參數(shù)。若不存在則模塊標(biāo)識(shí)應(yīng)該默認(rèn)定義為在加載器中被請(qǐng)求腳本的標(biāo)識(shí)。如果存在,那么模塊標(biāo)識(shí)必須為頂層的或者一個(gè)絕對(duì)的標(biāo)識(shí)。
第二個(gè)參數(shù),dependencies ,是一個(gè)當(dāng)前模塊依賴的,已被模塊定義的模塊標(biāo)識(shí)的數(shù)組字面量。
第三個(gè)參數(shù),factory,是一個(gè)需要進(jìn)行實(shí)例化的函數(shù)或者一個(gè)對(duì)象。
? 定義無依賴的模塊
?
define( {
? ? add : function( x, y ){
? ? ? ? return x + y ;
? ? }
} );
?
? 定義有依賴的模塊
?
define(["alpha"], function( alpha ){
? ? return {
? ? ? ? verb : function(){
? ? ? ? ? ? return alpha.verb() + 1 ;
? ? ? ? }
? ? }
});
?
? 定義數(shù)據(jù)對(duì)象模塊
?
define({
? ? users: [],
? ? members: []
});
?
?? 具名模塊
?
define("alpha", [ "require", "exports", "beta" ], function( require, exports, beta ){
? ? export.verb = function(){
? ? ? ? return beta.verb();
? ? ? ? // or:
? ? ? ? return require("beta").verb();
? ? }
});
?
? 包裝模塊
?
define(function(require, exports, module) {
? ? var a = require('a'),
? ? ? ? ? b = require('b');
?
? ? exports.action = function() {};
} );
?
不考慮多了一層函數(shù)外,格式和Node.js是一樣的:使用require獲取依賴模塊,使用exports導(dǎo)出API。
除了define外,AMD還保留一個(gè)關(guān)鍵字require。require 作為規(guī)范保留的全局標(biāo)識(shí)符,可以實(shí)現(xiàn)為 module loader,也可以不實(shí)現(xiàn)。
?
模塊加載
?
require([module], callback)
AMD模塊化規(guī)范中使用全局或局部的require函數(shù)實(shí)現(xiàn)加載一個(gè)或多個(gè)模塊,所有模塊加載完成之后的回調(diào)函數(shù)。
其中:
[module]:是一個(gè)數(shù)組,里面的成員就是要加載的模塊;
callback:是模塊加載完成之后的回調(diào)函數(shù)。
例如:加載一個(gè)math模塊,然后調(diào)用方法 math.add(2, 3);
require(['math'], function(math) {
math.add(2, 3);
});
?
3.RequireJS
RequireJS 是一個(gè)前端的模塊化管理的工具庫,遵循AMD規(guī)范,它的作者就是AMD規(guī)范的創(chuàng)始人 James Burke。所以說RequireJS是對(duì)AMD規(guī)范的闡述一點(diǎn)也不為過。
RequireJS 的基本思想為:通過一個(gè)函數(shù)來將所有所需要的或者說所依賴的模塊實(shí)現(xiàn)裝載進(jìn)來,然后返回一個(gè)新的函數(shù)(模塊),我們所有的關(guān)于新模塊的業(yè)務(wù)代碼都在這個(gè)函數(shù)內(nèi)部操作,其內(nèi)部也可無限制的使用已經(jīng)加載進(jìn)來的以來的模塊。
?
<script data-main='scripts/main' src='scripts/require.js'></script>
?
那么scripts下的main.js則是指定的主代碼腳本文件,所有的依賴模塊代碼文件都將從該文件開始異步加載進(jìn)入執(zhí)行。
define用于定義模塊,RequireJS要求每個(gè)模塊均放在獨(dú)立的文件之中。按照是否有依賴其他模塊的情況分為獨(dú)立模塊和非獨(dú)立模塊。
? 獨(dú)立模塊,不依賴其他模塊。直接定義:
define({
? ? method1: function(){},
? ? method2: function(){}
});
?
也等價(jià)于
define(function() {
return {
method1: function(){},
method2: function(){}
}
});
? 非獨(dú)立模塊,對(duì)其他模塊有依賴。
define([ 'module1', 'module2' ], function(m1, m2) {
? ? ...
});
?
或者:define(function(require) {
var m1 = require('module1'),
m2 = require('module2');
...
});
?
?
?
?
?
?
簡(jiǎn)單看了一下RequireJS的實(shí)現(xiàn)方式,其 require 實(shí)現(xiàn)只不過是提取 require 之后的模塊名,將其放入依賴關(guān)系之中。
?
? require方法調(diào)用模塊
在require進(jìn)行調(diào)用模塊時(shí),其參數(shù)與define類似。
require(['foo', 'bar'], function(foo, bar) {
? ? foo.func();
? ? bar.func();
} );
在加載 foo 與 bar 兩個(gè)模塊之后執(zhí)行回調(diào)函數(shù)實(shí)現(xiàn)具體過程。
官網(wǎng) (http://www.requirejs.org/)
API (http://www.requirejs.org/docs/api.html)
4.CMD和SeaJS
?
CMD是SeaJS 在推廣過程中對(duì)模塊定義的規(guī)范化產(chǎn)出
? 對(duì)于依賴的模塊AMD是提前執(zhí)行,CMD是延遲執(zhí)行。不過RequireJS從2.0開始,也改成可以延遲執(zhí)行(根據(jù)寫法不同,處理方式不通過)。
? CMD推崇依賴就近,AMD推崇依賴前置。
?
//AMD
define(['./a','./b'], function (a, b) {
?//依賴一開始就寫好
? ? a.test();
? ? b.test();
});
?
//CMD
define(function (requie, exports, module) {
? ? ?
? ? //依賴可以就近書寫
? ? var a = require('./a');
? ? a.test();
? ? ?
? ? ...
? ? //軟依賴
? ? if (status) {
? ? ?
? ? ? ? var b = requie('./b');
? ? ? ? b.test();
? ? }
});
?
雖然 AMD也支持CMD寫法,但依賴前置是官方文檔的默認(rèn)模塊定義寫法。
? AMD的API默認(rèn)是一個(gè)當(dāng)多個(gè)用,CMD嚴(yán)格的區(qū)分推崇職責(zé)單一。例如:AMD里require分全局的和局部的。CMD里面沒有全局的 require,提供 seajs.use()來實(shí)現(xiàn)模塊系統(tǒng)的加載啟動(dòng)。CMD里每個(gè)API都簡(jiǎn)單純粹。
?
5.?UMD
UMD是AMD和CommonJS的糅合
AMD模塊以瀏覽器第一的原則發(fā)展,異步加載模塊。
CommonJS模塊以服務(wù)器第一原則發(fā)展,選擇同步加載,它的模塊無需包裝(unwrapped modules)。
這迫使人們又想出另一個(gè)更通用的模式UMD (Universal Module Definition)。希望解決跨平臺(tái)的解決方案。
UMD先判斷是否支持Node.js的模塊(exports)是否存在,存在則使用Node.js模塊模式。
在判斷是否支持AMD(define是否存在),存在則使用AMD方式加載模塊。
?
(function (window, factory) {
? ? if (typeof exports === 'object') {
? ? ?
? ? ? ? module.exports = factory();
? ? } else if (typeof define === 'function' && define.amd) {
? ? ?
? ? ? ? define(factory);
? ? } else {
? ? ?
? ? ? ? window.eventUtil = factory();
? ? }
})(this, function () {
//module …
});
?
(function (root, factory) {
? ? if (typeof define === 'function' && define.amd) {
? ? ? ? // AMD
? ? ? ? define(['jquery', 'underscore'], factory);
? ? } else if (typeof exports === 'object') {
? ? ? ? // Node, CommonJS之類的
? ? ? ? module.exports = factory(require('jquery'), require('underscore'));
? ? } else {
? ? ? ? // 瀏覽器全局變量(root 即 window)
? ? ? ? root.returnExports = factory(root.jQuery, root._);
? ? }
}(this, function ($, _) {
? ? //? ? 方法
? ? function a(){};? ? //? ? 私有方法,因?yàn)樗鼪]被返回 (見下面)
? ? function b(){};? ? //? ? 公共方法,因?yàn)楸环祷亓?/p>
? ? function c(){};? ? //? ? 公共方法,因?yàn)楸环祷亓?/p>
?
? ? //? ? 暴露公共方法
? ? return {
? ? ? ? b: b,
? ? ? ? c: c
? ? }
}));
?
轉(zhuǎn)載于:https://www.cnblogs.com/Super-scarlett/p/8260458.html
總結(jié)
以上是生活随笔為你收集整理的CommonJS/AMD/CMD/UMD的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【图文详细教程】maven3安装配置+e
- 下一篇: 2017美国专利榜:IBM称霸全球!华为