一、什么是模块?
- 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行在一起。
- 块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信。
二、模块化开发的好处
-
避免变量污染,命名冲突
-
提高代码复用率
-
提高了可维护性
-
方便依赖关系管理,更好的分离, 并且按需加载
三、模块化的演化
1、全局function模式
- 编码: 将不同的功能封装成不同的全局函数
- 缺点: 污染全局命名空间, 容易引起命名冲突或数据不安全,而且模块成员之间看不出直接关系
function m1(){ //... } function m2(){ //... }
2、namespace模式 : 简单对象封装
- 优势: 减少了全局变量,解决命名冲突
- 缺点: 数据不安全(外部可以直接修改模块内部的数据),会暴露所有模块成员,内部状态可以被外部改写。
let myModule = { data: 'www.baidu.com', foo() { console.log(`foo() ${this.data}`) }, bar() { console.log(`bar() ${this.data}`) } } myModule.data = 'other data' //能直接修改模块内部的数据 myModule.foo() // foo() other data
3、IIFE模式:匿名函数自调用(闭包)
- 编码: 将数据和行为封装到一个函数内部, 通过给window添加属性来向外暴露接口
- 优点: 数据是私有的, 外部只能通过暴露的方法操作
- 缺点: 如果当前这个模块依赖另一个模块怎么办?
比如如下的模块代码:
(function(window) { let data = 'www.baidu.com'; //操作数据的函数 function foo() { //用于暴露公有函数 console.log(`我是函数foo(),data为:${data}`) } function bar() { //用于暴露公有函数 console.log(`我是函数bar(),data为:${data}`); otherFun() //内部调用 } function otherFun() { //内部私有的函数 console.log('我是函数otherFun()') } //暴露行为 window.myModule = { foo, bar } //ES6写法 })(window);
调用方法如下代码所示:
<script type="text/javascript" src="module.js"></script> <script type="text/javascript"> myModule.foo(); myModule.bar(); console.log(myModule.data);//undefined 不能访问模块内部数据 myModule.data = 'xxxx';//不是修改的模块内部的data myModule.foo() //没有改变 </script>
结果如下所示:
4、IIFE模式增强 : 引入依赖
比如引入jQuery
比如如下的模块代码:
(function(window, $) { let data = 'www.baidu.com' //操作数据的函数 function foo() { //用于暴露公有函数 console.log(`foo() ${data}`) $('body').css('background', 'red') } function bar() { //用于暴露公有函数 console.log(`bar() ${data}`) otherFun() //内部调用 } function otherFun() { //内部私有的函数 console.log('otherFun()') } //暴露行为 window.myModule = { foo, bar } })(window, jQuery)
调用方法如下代码所示:
<!-- 引入的js必须有一定顺序 --> <script type="text/javascript" src="jquery-1.10.1.js"></script> <script type="text/javascript" src="module.js"></script> <script type="text/javascript"> myModule.foo() </script>