CommonJS
node实现就是在commonJS规范基础上实现。node作为服务端语言,源码文件都在硬盘上,读取很快,同步加载即可,无需使用异步方案。
AMD
AMD是为了解决浏览器端异步模块加载化方案,主要由require.config()、define()、require 三个函数实现。
require.config() 用于声明基本路径和模块名称;
define() 用于定义模块对象;
require() 则用于加载模块并使用。
/** 网页中引入require.js及main.js **/
<script src="js/require.js" data-main="js/main"></script>
“js/require.js” 是实现 AMD 规范的类库文件,是任何使用 AMD 规范的网页都需要加载的;
“js/main” 是开发者的代码主文件,在这个文件中加载并使用自定义模块,示例代码如下:
/** main.js 入口文件/主模块 **/
// 首先用config()指定各模块路径和引用名
require.config({
baseUrl: 'js/lib',
paths: {
jquery: 'jquery.min', // 实际路径为js/lib/jquery.min.js
underscore: 'underscore.min'
}
})
// 执行基本操作
require(['jquery', 'underscore', 'math'], function ($, _, math) {
// 在这里$代表jqurey、_代表underscore
var sum = math.add(10, 20)
$('#sum').html(sum)
})
而用于模块的定义,在其它 JS 文件中是这样声明的:
// 定义math.js模块
define(function () {
var basicNum = 0
var add = function (x, y) {
return x + y
}
return {
add: add,
basicNum: basicNum
}
})
如果在一个模块定义中依赖另一个模块对象,可以这样声明:
// 定义一个依赖underscore模块的模块
define(['underscore'], function (_) {
var classify = function (list) {
_.countBy(list, function (num) {
return num > 30 ? 'old' : 'young'
})
}
return {
classify: classify
}
})
AMD缺陷:对于依赖的模块无论实际需要与否,都会先加载并执行。
define(['a', 'b', 'c', 'd', 'e', 'f'], function (a, b, c, d, e, f) {
// 等于在最前面声明并初始化了要用到的所有模块
if (false) {
// 即便没用到某个模块 b,但 b 还是提前执行了
b.foo()
}
})
在上面的代码中,模块 a、b、c、d、e、f 都会加载并执行,即使它们在实际的模块代码中没有被用到。为了解决这个“浪费”的问题,CMD 规范应运而生。
CMD
应该说cmd是站在commonJS,AMD的肩膀上发展起来的。与CMD很相似,AMD 规范是依赖前置、模块提前加载并执行;CMD 是依赖后置、模块懒惰加载再执行。
**
define(function(require, exports, module) {
var a = require('./a') // 在需要时申明、加载和使用
a.doSomething()
if (false) {
var b = require('./b')
b.doSomething()
}
})
参考:
前端模块化详解(完整版):https://segmentfault.com/a/1190000017466120#articleHeader1