一种管理代码的方式,核心是将相关的代码弄成独立的单元(模块)。
发展历程
script 标签:最开始通过在 HTML 里面引入不同的 script 标签,强行“模块化”
<!DOCTYPE html>
<htlm lang='zh'>
<head>
<meta charse="utf=-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>xx</title>
</head>
<body>
<div>xxx</div>
<script src="https://xxxx/jquery.js"></script>
<script src="./main.js"></script>
<script src="./tool.js"></script>
<!-- <script src="./*.js"></script> -->
</body>
</htlm>
缺点:变量会产生冲突
IIFE:立即执行函数,借助于函数作用域,使用“模块化”
也可以看做闭包
const moduleA = (function() {
let count = 0
const addCount = () => ++count
const getCount = () => count
return {
getCount,
addCount
}
})()
moduleA.addCount()
moduleA.getCount() // 1
const moduleB = (function() {
let count = 0
const addCount = () => count + 2
const getCount = () => count
return {
getCount,
addCount
}
})()
moduleB.addCount()
moduleB.getCount() // 2
CJS(CommonJS) :支持node端的模块同步加载规范,通过require、exports实现
// moduleA.js
let count = 0
const addCount = () => count + 1
const getCount = () => count
exports.addCount = addCount
exports.getCount = getCount
// main.js
const moduleA = require('./moduleA.js')
moduleA.addCount()
moduleA.getCount() // 1
缺点:只支持同步,容易阻塞
AMD(Async Module Define) :支持浏览器端的模块异步加载规范,著名产物require.js
// 定义模块
define('moduleA', ['deps1', 'deps2'], function(deps1, deps2) {
let count = 0
const addCount = () => count + 1
const getCount = () => count
return {
getCount,
addCount
}
})
// 使用模块
require(['moduleA'], function(moduleA) {
moduleA.addCount()
moduleA.getCount() // 1
})
缺点:语法繁琐
UMD(Universal Module Define) :一种兼容前面模块的加载规范
本质是利用 IIFE 做兼容,类似下面的代码
(function(root, factory) {
const moduleName= factory.name
if(define && typeof define === 'function') {
// 兼容 AMD
define(moduleName, [], factory)
} else if(typeof exports === 'object') {
// 兼容 CJS
exports[moduleName] = factory()
} else {
// 挂载到全局
root[moduleName] = factory()
}
})(this, function moduleA() {
let count = 0
const addCount = () => count + 1
const getCount = () => count
return {
getCount,
addCount
}
})
ESM(ES6 Module) :ECMA 支持的模块加载机制,通过import、export实现
这也是我们目前最常用的方式,支持异步
模块化的目的:1、隔离代码逻辑;2、扩展协同方便性;
最终实现了一切皆模块,是前端工程化的基石。