• 【JS】模块化的几种解决方案(AMD、CMD、ES6、CommonJS)


    参考: https://juejin.cn/post/6844903744518389768
    至少需要知道 CMD、AMD、CommonJS、ESM 方法

    namespace

    不常用,核心思路是通过一个对象隔离变量

    IIFE

    优点是不会污染全局变量,且能实现数据隐藏(不把数据挂到 root 上即可)。但是调用其他模块很困难,可以通过传入多个参数实现模块的调用。

    (function(root, $) {
    	root.sum = function() {
    	}
    	$('body').append('

    hello world

    '
    ) })(window, jquery)
    • 1
    • 2
    • 3
    • 4
    • 5

    CommonJS

    服务端的模块化解决方案,导入模块是同步的(区别 AMD),因为服务端的文件一般在本地所有导入无需考虑速度问题。
    此外,还需注意 CommonJS 导入的数据的原数据的拷贝,也就说改变导入的数据不会影响原数据。

    CommonJS 认为每个文件就是一个单独的模块,其中内置 module 变量,通过 module.exports 对象导出数据,而导入数据时,导入的就是 module.exports 中的数据。

    1.js

    module.exports = {
      x: 1,
      y: 2
    }
    
    // 或者用 exports.xxx 给 exports 对象添加属性
    exports.z = 3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.js 引入 1.js 的内容

    const data = require('./1.js')
    console.log(data) // { x: 1, y: 2, z: 3 }
    
    • 1
    • 2

    需要注意的是,直接给 exports 变量赋值为新对象是无法导出数据的,因为这样 JS 会把当前文件的 exports 的地址指向新创建的对象,而不是把 module.exports 的地址指向新创建的对象。

    module.exports === exports // true
    
    // 改变了 exports 的指向 
    exports = {
      x: 1
    }
    
    // 我们实际导出的是 module.exports 的内容,而不是 exports 这个变量的内容
    
    module.exports === exports // false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    AMD

    • 异步加载模块
    • 可以用于浏览器环境
    • 使用 require.js

    基本写法

    // 无模块依赖
    // sum.js
    define(function() {
      function sum(a, b) {
    	return a + b
      }
    
      // 导出函数
      return { sum }
    })
    
    // calc.js
    // 依赖 sum.js,第一个参数为模块名,函数参数为模块对象
    define(['sum'], function(sum) {
      let a = 1, b = 2;
      const c = sum(a, b);
      return { c }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    配置

    // main.js
    (function() {
      require.config({
        baseUrl: 'js/', // 基本路径 出发点在根目录下
        paths: {
          //映射: 模块标识名: 路径
          sum: './modules/sum', //此处不能写成alerter.js,会报错
          calc: './modules/calc'
        }
      })
    
      // 导入 sum 并使用
      require(['sum'], function(sum) {
        console.log(sum(1, 2))
      })
    })()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    index.js 引入 require.js 同时设置入口文件的地址

    DOCTYPE html>
    <html>
      <head>
        <title>Modular Demotitle>
      head>
      <body>
        
        <script data-main="js/main" src="js/libs/require.js">script>
      body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    CMD

    • 结合了 CommonJS 和 AMD 的优点
    • 专门用于客户端
    • 模块异步加载
    • sea.js 实现(最后 release 在 2014 年)
      使用方法
    // 1.js 提供 sum 函数
    define(function(requrie, exports, module) {
      exports.sum = function(a, b) { // or module.exports = {}
    	return a + b
      }
    })
    
    // main.js 导入
    define(function(require) {
      // 导入路径为当前模块所在的相对路径
      const { sum } = requrie('./1')
      console.log(sum)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在 html 中初始化

    <script src="./js/sea.js">script>
    <script>
    // 注册入口模块
    seajs.use('./js/main')
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    可以看到,seajs 提供了一个 define 函数用于导入/导出模块,该函数接受一个回调函数,这个回调函数有三个参数:

    • require 用于导入其它模块
    • exports 用于导出一个数据
    • module.exports 导出一个对象
      可以发现这三个参数和 CommonJS 提供的很像。

    ES6 模块化

    • 从语言层面解决了模块化的问题
    • 服务端和客户端都支持
    • 导入的数据和 CommonJS 不同,是引用类型
    • 使用 export 和 export default 导出数据
    • 使用 import … from 导入数据
    // sum.js
    export {
      sum(a, b) {
        return a + b
      }
    }
    
    export default const VERSION = 1.1 
    
    // main.js
    import VERSION, { sum } from 'sum'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    总结

    摘抄自
    作者:浪里行舟
    链接:https://juejin.cn/post/6844903744518389768
    来源:稀土掘金

    • CommonJS规范主要用于服务端编程,加载模块是同步的,这并不适合在浏览器环境,因为同步意味着阻塞加载,浏览器资源是异步加载的,因此有了AMD CMD解决方案。
    • AMD规范在浏览器环境中异步加载模块,而且可以并行加载多个模块。不过,AMD规范开发成本高,代码的阅读和书写比较困难,模块定义方式的语义不顺畅。
    • CMD规范与AMD规范很相似,都用于浏览器编程,依赖就近,延迟执行,可以很容易在Node.js中运行。不过,依赖SPM 打包,模块的加载逻辑偏重
    • ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
  • 相关阅读:
    第八章 排序 七、堆排序
    自动驾驶仿真:角雷达坐标系转换详解
    RK3568平台开发系列讲解(LCD篇)DRM 显示框架
    Java 调用 Cpp 代码简单示例
    趣学算法:分治算法
    【Linux】环境变量
    HTML5拖放(Drag and Drop)全面指南:让网页互动起来
    五、【Vue-Router】路由的params参数
    在线教育项目【老师管理-前端实现】
    ffmpeg抠图
  • 原文地址:https://blog.csdn.net/qq_39559879/article/details/126640020