# 模块化
模块是具有高内聚性和可复用性的结构。
# 1. IIFE(立即调用函数表达式)
ES6 之前的模块使用函数作用域和立即调用函数表达式将模块定义封装在匿名闭包中。
(function() {
const fn1 = function() {}
return {
// 这里写暴露的公共 api
fn1,
}
})();
1
2
3
4
5
6
7
2
3
4
5
6
7
# 2. CommonJS (同步模块)
CommonJS 规范概述了同步声明依赖的模块定义,以服务器端为目标环境,不能在浏览器中直接运行。
使用 require() 引入依赖,使用 exports 对象定义自己的公共 API。
// 模块定义 moduleA.js
// 在 module.exports 对象上定义自己的公共接口
let obj = 'moduleA 的内部属性'
module.exports = {
obj
}
// 也可使用 exports.obj = obj
// exports = module.exports 不能直接赋值
// 模块引入 moduleB.js
const moduleA = require('./moduleA.js')
console.log(moduleA.obj) // moduleA 的内部属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
- 单例模式:无论一个模块被引入多少次,最终只加载一次
- 支持动态依赖
- 使用
require/module.exports
全局属性
# 3. AMD (异步模块)
AMD 模块定义系统以浏览器为目标执行环境。
一般策略是让模块声明自己的依赖,在浏览器运行时按需获取。
其实现核心是用函数包装模块定义,包装函数为全局 define
参数。
// 全局定义函数
/*
@params id :定义的模块名字
@params dependencies : 当前模块依赖的,已被模块定义的模块标识的数组字面量
默认为["require", "exports", "module"]
@factory : 模块初始化执行的函数
*/
define(id?, dependencies?, factory);
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 4. CMD
CMD 即Common Module Definition通用模块定义,CMD规范是国内发展出来的,就像AMD有个requireJS,CMD有个浏览器的实现SeaJS,SeaJS要解决的问题和requireJS一样,只不过在模块定义方式和模块加载(可以说运行、解析)时机上有所不同
AMD和CMD最大的区别是对依赖模块的执行时机处理不同,注意不是加载的时机或者方式不同
# 5. UMD (通用模块)
统一了 CommonJS 和 AMD 生态系统,本质上是在启动时进行环境检测,然后进行适当配置,所有逻辑包装在一个立即调用的函数表达式中。
以下是样板代码,可以由构建工具自动生成,开发者只需专注于模块的内容。
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD 模块
define(['moduleB'], factory)
} else if (typeof module === 'object' && module.exports) {
// Node 环境,不支持严格 CommonJS ,但可以支持 module.exports 类 CommonJS 环境
module.exports = factory(require(' moduleB '))
} else {
// 浏览器全局上下文
root.returnExports = factory(root.moduleB)
}
})(this, function(moduleB) {
// 以某种方式使用 moduleB 模块
// 将返回值作为模块的导出
return {}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 6. ES6 模块
ES6 模块系统是集 AMD 和 CommonJS 之大成者。
// 模块导出
export const a = 1
// 或
const a = 1
export a
// 定义默认导出
export default a
// 模块导入
import {a} from 'moduleA'
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11