JavaScript模块化进化史

804 阅读2分钟

## JS模块化 

* 什么是模块?

* 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起

* 块的内部数据/实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信

* 一个模块的组成

* 数据--->内部的属性

* 操作数据的行为--->内部的函数

* 模块化

* 编码时是按照模块一个一个编码的, 整个项目就是一个模块化的项目

## 模块化进化史 

1. 全局function模式 

 * module1.js

    //数据
    let data = '123'
   
    //操作数据的函数
    function foo() {
      console.log(`foo() ${data}`)
    }

    function bar() {
      console.log(`bar() ${data}`)
    }

* module2.js

    let data2 = 'other data';    
    function foo() {  
      //这里与另一个模块中的函数冲突了
      console.log(`foo() ${data2}`)
    }

* test.html

    <script type="text/javascript" src="module1.js"></script>
    <script type="text/javascript" src="module2.js"></script>
    <script type="text/javascript">
      let data = "我是修改后的数据"
      foo()
      bar()
    </script>

* 说明:

* 全局函数模式: 将不同的功能封装成不同的全局函数

* 问题: Global被污染了, 很容易引起命名冲突

2. namespace模式 

 * module1.js

    let myModule = {
      data: 'module1 123123',
      foo() {
        console.log(`foo() ${this.data}`)
      },
      bar() {
        console.log(`bar() ${this.data}`)
      }
    }

* module2.js

    let myModule2 = {
      data: 'module2 123123',
      foo() {
        console.log(`foo() ${this.data}`)
      },
      bar() {
        console.log(`bar() ${this.data}`)
      }
    }

* test.html

    <script type="text/javascript" src="module1.js"></script>
    <script type="text/javascript" src="module2.js"></script>
    <script type="text/javascript">
      myModule.foo()
      myModule.bar() 
      myModule2.foo()
      myModule2.bar()
 
      //可以直接修改模块内部的数据
      myModule.data = 'other data' 
      myModule.foo()
    </script>

* 说明

* namespace模式: 简单对象封装

* 作用: 减少了全局变量

* 问题: 依然可以修改模块内部代码,不安全

3. IIFE模式 

 * module3.js

    (function (window) {
      //数据
      let data = '13123123'
      //操作数据的函数
      function foo() { //向外暴露的内部私有函数
        console.log(`foo() ${data}`)
      }

      function bar() {//向外暴露的内部私有函数
        console.log(`bar() ${data}`)
        otherFun() //内部调用
      } 

      function otherFun() { //未暴露的内部私有函数
        console.log('otherFun()')
      }

      //暴露行为
      window.myModule = {foo, bar}
    })(window)

* test.html

    <script type="text/javascript" src="module3.js"></script>
    <script type="text/javascript">
      myModule.foo()
      myModule.bar()
      //myModule.otherFun()  //报错:myModule.otherFun is not a function
      console.log(myModule.data) //undefined 不能访问模块内部数据
      myModule.data = 'xxxx' //并不是修改的模块内部的data
      myModule.foo() //未受影响
    </script>

* 说明:

* IIFE模式: 匿名函数自调用(闭包)

* IIFE : immediately-invoked function expression(立即调用函数表达式)

* 作用: 数据是私有的, 外部只能通过暴露的方法操作

* 问题: 如果当前这个模块依赖另一个模块怎么办?

4. IIFE模式增强 

 * 引入jquery到项目中

* module4.js

    (function (window, $) {
      //数据
     let data = '12312312'    
      //操作数据的函数
      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)

* test4.html

    <script type="text/javascript" src="jquery-1.10.1.js"></script>
    <script type="text/javascript" src="module4.js"></script>
    <script type="text/javascript">
      myModule.foo()
    </script>

* 说明

* IIFE模式增强 : 引入依赖

* 这就是现代模块实现的基石

5. 页面加载多个js的问题 

 * 页面:

    <script type="text/javascript" src="module1.js"></script>
    <script type="text/javascript" src="module2.js"></script>
    <script type="text/javascript" src="module3.js"></script>
    <script type="text/javascript" src="module4.js"></script>
    <script type="text/javascript" src="module5.js"></script>
    <script type="text/javascript" src="module6.js"></script>
    <script type="text/javascript" src="module7.js"></script>
    <script type="text/javascript" src="module8.js"></script>
    <script type="text/javascript" src="module9.js"></script>
    <script type="text/javascript" src="module10.js"></script>
    <script type="text/javascript" src="module11.js"></script>
    <script type="text/javascript" src="module12.js"></script>

* 说明

* 一个页面需要引入多个js文件

* 问题:

* 请求过多

* 依赖模糊

* 难以维护

* 这些问题可以通过现代模块化编码和项目构建来解决