js模块化编程

全局function模式

  • module1.js
    //数据
    let data = 'atguigu.com'
    
    //操作数据的函数
    function foo() {
      console.log(`foo() ${data}`)
    }
    function bar() {
      console.log(`bar() ${data}`)
    }
    
  • module2.js
    let data2 = 'other data'
    
    function foo() {  //与另一个模块中的函数冲突了
      console.log(`foo() ${data2}`)
    }
    
  • test1.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被污染了, 很容易引起命名冲突

namespace模式

  • module1.js
    let myModule = {
      data: 'atguigu.com',
      foo() {
        console.log(`foo() ${this.data}`)
      },
      bar() {
        console.log(`bar() ${this.data}`)
      }
    }
    
  • module2.js
    let myModule2 = {
      data: 'atguigu.com2222',
      foo() {
        console.log(`foo() ${this.data}`)
      },
      bar() {
        console.log(`bar() ${this.data}`)
      }
    }
    
  • test2.html
    <script type="text/javascript" src="module2.js"></script>
    <script type="text/javascript" src="module22.js"></script>
    <script type="text/javascript">
      myModule.foo()
      myModule.bar()
    
      myModule2.foo()
      myModule2.bar()
    
      myModule.data = 'other data' //能直接修改模块内部的数据
      myModule.foo()
    
    </script>
    

说明

* namespace模式: 简单对象封装
* 作用: 减少了全局变量
* 问题: 不安全

IIFE模式

  • module3.js
    (function (window) {
      //数据
      let data = 'atguigu.com'
    
      //操作数据的函数
      function foo() { //用于暴露有函数
        console.log(`foo() ${data}`)
      }
    
      function bar() {//用于暴露有函数
        console.log(`bar() ${data}`)
        otherFun() //内部调用
      }
    
      function otherFun() { //内部私有的函数
        console.log('otherFun()')
      }
    
      //暴露行为
      window.myModule = {foo, bar}
    })(window)
    
  • test3.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(立即调用函数表达式)
* 作用: 数据是私有的, 外部只能通过暴露的方法操作
* 问题: 如果当前这个模块依赖另一个模块怎么办?

IIFE模式增强

  • 引入jquery到项目中
  • module4.js
    (function (window, $) {
      //数据
      let data = 'atguigu.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)
    
  • 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模式增强 : 引入依赖
* 这就是现代模块实现的基石

页面加载多个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>
    
  • 说明
    • 一个页面需要引入多个js文件
    • 问题:
      • 请求过多
      • 依赖模糊
      • 难以维护
    • 这些问题可以通过现代模块化编码和项目构建来解决

现代模块化编码

CommonJS

* Node.js : 服务器端
* Browserify : 浏览器端    也称为js的打包工具
* 基本语法:
  * 定义暴露模块 : exports
    ```
    exports.xxx = value
    module.exports = value
    ```
  引入模块 : require
    ```
    var module = require('模块名/模块相对路径')
    ```
* 引入模块发生在什么时候?
  * Node : 运行时, 动态同步引入
  * Browserify : 在运行前对模块进行编译/转译/打包的处理(已经将依赖的模块包含进来了), 
              运行的是打包生成的js, 运行时不存在需要再从远程引入依赖模块

AMD : 浏览器端

* require.js
* 基本语法
  * 定义暴露模块: define([依赖模块名], function(){return 模块对象})
  * 引入模块: require(['模块1', '模块2', '模块3'], function(m1, m2){//使用模块对象})
  * 配置: 
    ```
    require.config({
      //基本路径
      baseUrl : 'js/',
      //标识名称与路径的映射
      paths : {
        '模块1' : 'modules/模块1',
        '模块2' : 'modules/模块2',
        'angular' : 'libs/angular',
        'angular-messages' : 'libs/angular-messages'
      },
      //非AMD的模块
      shim : {
        'angular' : {
            exports : 'angular'
        },
        'angular-messages' : {
            exports : 'angular-messages',
            deps : ['angular']
        }
      }
    })
    ```

CMD : 浏览器端

* sea.js
* 基本语法
  * 定义暴露模块: 
    ```
    define(function(require, module, exports){
      通过require引入依赖模块
      通过module/exports来暴露模块
      exports.xxx = value
    })
    ```
  * 使用模块seajs.use(['模块1', '模块2'])

ES6

* ES6内置了模块化的实现
* 基本语法
  * 定义暴露模块 : export
    * 暴露一个对象: 
      ```
      export default 对象
      ```
    * 暴露多个: 
      ```
      export var xxx = value1
      export let yyy = value2
      
      var xxx = value1
      let yyy = value2
      export {xxx, yyy}
      ```
          
  * 引入使用模块 : import
    * default模块:
      ```
      import xxx  from '模块路径/模块名'
      ```
    * 其它模块
      ```
      import {xxx, yyy} from '模块路径/模块名'
      import * as module1 from '模块路径/模块名'
      ```
* 问题: 所有浏览器还不能直接识别ES6模块化的语法  
* 解决:
    * 使用Babel将ES6--->ES5(使用了CommonJS) ----浏览器还不能直接支行
    * 使用Browserify--->打包处理----浏览器可以运行

关于本文说明:

1.文档来自于 尚硅谷;本文仅用于个人学习

posted @ 2023-11-01 15:57  啄木鸟伍迪  阅读(13)  评论(0)    收藏  举报
//火箭 GenerateContentList();