什么是模块化
- 将一个复杂程序按照一定的规则封装成几个块(模块),并组合在一起;
- 模块的内部数据与实现是私有的,只是向外暴漏一些接口(方法)与外部通信。
代码抽象、代码封装、代码复用、依赖管理
为什么需要模块化
没有模块化会出现:
- 变量和方法容易出现命名冲突,造成全局污染
- 加载资源的方式通过script标签从上到下,会导致引入多个scipt:请求过多、依赖模糊(加载顺序模糊)、难以维护
模块化的好处:
- 避免了命名冲突,减少命名空间污染
- 更好的分离,按需加载
- 高复用性、高维护性
模块化规范
CommonJS、AMD、CMD、ES6规范
CommonJS:
作用于服务器;在服务器端,模块的加载是同步加载的;在浏览器端,模块需要提前编译打包处理。
语法:
module.exports = value 导出
require(‘引入模块路径’) 引入
//a.js 导出
module.exports = {foo,bar}
//b.js 引入
const {foo,bar} = require('./a.js')
特点:
- 所有代码都运行在模块作用域,不会污染全局作用域
- 模块是同步加载的,只有加载完成,才会进行后面的加载
- 模块首次执行后会缓存,再次加载返回的是缓存结果,如果想要再次执行,需要清除缓存
- require返回的是被输出值的拷贝值,模块内部的变化不会影响到这个值
AMD-require.js
Asynchronous ModuleDefinition
异步模块定义,采用异步方式加载模块。所有依赖模块语句都定义在一个回调函数中,等到模块加载完成后,执行回调函数。
语法:
用require.config()指定引用路径,用define()定义模块,用require加载模块。
代表库require.js,需要引入这个库。
//定义有依赖关系的模块
define(['module1','module2'],function(m1,m2){
return 模块
})
//引入加载
require(['module1','module2'],function(m1,m2){
使用m1,m2
})
CMD-sea.js
专门作用与浏览器端,模块的加载是异步的,模块使用时才会加载。CMD是整合了AMD和CommonJS的特点。 在sea.js中,所有JS模块遵循CMD
语法:
用define()定义模块,seajs.use引用模块
//module1
define(function(require,exports,module){
vae data = 'liyiran'
function show(){
console.log('module1 show()'+data)
}
//向外暴露
exports.show = show
})
//module2
define(function(require,exports,module){
module.exports = {
msg:'liyiran'
}
})
//引入main.js
define(function(require){
var m1 = require('./module1')
var m2 = require('./module2')
})
//在html文件中引入
<script type ="text/javascript">
seahs.use('./js/modules/main')
</script>
ES6模块化
使用export 导出、import导入
export:用于规定模块的对外接口
import:用于输入其他模块提供的功能
- 使用import,需要指导加载的变量名或函数名,否则无法加载。
- 可以使用用export default命令,为模块指定默认输出,其他模块加载模块时,import命令可以该匿名函数指定任意名字。
ES6模块和CommonJS模块的差异
- CommonJS 模块输出的是一个值的拷贝,ES6模块输出的是值的引用。
- CommonJS模块是运行时加载,ES6模块时编译时输出接口
- ES6 模块的运行机制与 CommonJS 不一样。ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
- CommonJS主要作用于服务器端。ES6既可以用于服务器端也可以用于浏览器端。
总结
- CommonJS:
规范主要用于服务端编程,加载模块是同步的,这并不适合在浏览器环境,因为同步意味着阻塞加载,浏览器资源是异步加载的,因此有了AMD CMD解决方案。 - AMD规范
在浏览器环境中异步加载模块,而且可以并行加载多个模块。不过,AMD规范开发成本高,代码的阅读和书写比较困难,模块定义方式的语义不顺畅。 - CMD规范
与AMD规范很相似,都用于浏览器编程,依赖就近,延迟执行,可以很容易在Node.js中运行。不过,依赖SPM 打包,模块的加载逻辑偏重 - ES6 在语言标准的层面上,
实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。