前言:
为什么我们需要模块化开发,模块化开发的好处有哪些? 首先我们先说一下非模块化的开发方式带来的弊端。 非模块化开发中会导致一些问题的出现,变量和函数命名可能相同,会造成变量污染和冲突,并且出错时候很难排查。耦合程度高,不符合软件开发中的高内聚和低耦合的原则,所以我们就可以总结一下模块化开发的好处了:
为什么我们需要模块化开发,模块化开发的好处有哪些? 首先我们先说一下非模块化的开发方式带来的弊端。 非模块化开发中会导致一些问题的出现,变量和函数命名可能相同,会造成变量污染和冲突,并且出错时候很难排查。耦合程度高,不符合软件开发中的高内聚和低耦合的原则,所以我们就可以总结一下模块化开发的好处了:
- 解决项目中的变量污染问题。
- 开发效率高,有利于多人协同开发。
- 职责单一,方便代码重用和维护 。
- 解决文件依赖问题,无需关注引包顺序 。
模块化开发的演变过程
- 普通的函数封装
- 封装成对象
- 私有公有成员分离 (使用自执行函数,避免变量污染)
- 模块的维护和扩展(用多个自执行函数把模块分离开来,使用开闭原则—去增添功能,而尽量不要修改原来的代码,)
- 可以添加模块的第三方依赖(比如添加jQuery的$,$作为一个编程的接口,降低程序之间的耦合度)
模块化的规范
服务端规范 — CommonJs
作为服务器端的开发,不会经过网络传输,所以包的加载几乎都是瞬间完成的,只有加载完成了,才能执行操作,所以commonjs是同步的,nodejs就是实现了这种规范。
浏览器端规范 — AMD 和 CMD
浏览器端的规范,因为所有的文件请求都要经过网络传输,很多文件的加载会有不确定因素存在为了解决这个问题,浏览器端出来了这两个规范。
CMD
CMD在模块定义当中有三个变量,分别是require,exports,module.除了这三个变量可以辨识CMD外,define函数还有一个公有属性define.cmd。我们也可以监测这个值来判断是否是cmd。
如果想要对外提供接口的话,可以将接口绑到exports(module.exports)。
function MyModule() { // ...}
if(typeof module !== `undefined` && typeof exports === `object` && define.cmd) {
module.exports = MyModule;
}如果需要支持除了cmd之外的其他符合CommonJS的标准,请去掉define.cmd
AMD
AMD规范中,define函数同样有一个公有属性define.amd。
AMD中的参数便是这个模块的依赖,那么如何在AMD中提供接口呢?它是返回一个对象,这个对象就作为模块的接口,故我们可以这样写:
function MyModule() {
// ...
}
if(typeof define === `function` && define.amd) {
define(function() {
return MyModule;
});
}UMD
我们除了提供AMD模块的接口,CMD模块接口,还得提供原生的JS接口
UMD 叫做通用模块定义规范(Universal Module Definition)。也是随着大前端的趋势所诞生,它可以通过运行时或者编译时让同一个代码模块在使用 CommonJs、CMD 甚至是 AMD 的项目中运行。未来同一个 JavaScript 包运行在浏览器端、服务区端甚至是 APP 端都只需要遵守同一个写法就行了。
它没有自己专有的规范,是集结了 CommonJs、CMD、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
});总结