模块化的主要作用是抽离公共代码,隔离作用域,避免变量冲突等。
大概经历了以下发展历程:
IIFE(立即执行函数)
(function(){
return {
data:[]
}
})()
AMD
使用RequireJs来编写模块化。特点:依赖前置,依赖必须提前声明好。
//a.js 暴露模块
define('./a.js',function(code){
return { msg: 'Hello AMD'}
})
//b.js 引入模块
require(['./a.js], function(ModuleA){
console.log(ModuleA.msg)
})
CMD
使用SeaJs来编写模块化。特点:依赖就近,可以使用的时候在引入模块
//a.js 暴露模块
define(function(require, exports, module){
exports.msg = 'Hello CMD'
})
//b.js 引入模块
define(function(require, exports, module){
var moduleA = require('./a.js')
console.log(moduleA.msg)
})
UMD: 通用模块定义规范(Universal Module Definition)
同时兼容CommonJs、AMD。
((root, factory) => {
if (typeof define === 'function' && define.amd) {
//AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
//CommonJS
var $ = requie('jquery');
module.exports = factory($);
} else {
root.testModule = factory(root.jQuery);
}
})(this, ($) => {
//todo
});
CommomJS
用于服务器端,nodejs 中自带的模块化。特点是模块运行时同步加载。exports实际上是一个对module.exports的引用。注意,不能给exports赋值,否则会断开与module.exports的连接。
//a.js 暴露模块
// 默认加了一行var exports = module.exports
exports.a = 'hello world'
//b.js
const moduleA = require('./a.js')
console.log(moduleA.a)
ES6 Module
import、export 。 ES6 模块是编译时加载。
ES6 Module与CommonJS模块的差异,主要有两个:
CommonJS 模块输出的是一个值的拷贝(一旦输出之后,无论模块内部怎么变化,都无法影响之前的引用),ES6 模块输出的是值的引用(模块内部的原始值变了, import加载的模块也会变)。
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。