规范的演变

120 阅读2分钟

在没有工具和规范下,对模块化的演变

基于文件划分模块方式

缺点:所有模块都直接在全局工作,没有私有空间,所有成员都可以在模块外部被访问

基于文件划分模块方式 —— 每个模块只暴露一个全局对象

缺点:通过「命名空间」减小了命名冲突的可能,但还是没有私有空间,所有模块成员仍然可以在模块外部被访问或修改,而且也无法管理模块之间的依赖关系

立即执行函数(IIFE)

实现:每个模块成员都放在一个函数提供私有作用域中,对需要暴露给外部的成员,通过挂在到全局上实现

立即执行函数(IIFE)—— 参数的方式传入依赖项

模块化演变

CommonJS 规范(同步加载模块)

  1. 允许模块通过 require 方式来同步加载所要依赖的其他模块,然后通过 exports 或 modules.exports 来暴露
  2. CommonJS 规范主要是用于服务端的模块化规范;在服务端,模块的加载是运行时同步加载的。而在浏览器端的资源是异步加载的,模块需要提前编译打包处理

AMD 规范(异步加载模块)

  1. 完整描述了模块的定义,依赖关系,引用关系以及加载机制
  2. AMD 对应的就是很有名的 RequireJS
  3. 即RequireJS是预先把依赖的模块执行。
    执行流程:
    1. require 函数检查依赖的模块,根据配置文件,获取js文件的实际路径
    2. 根据 js 文件实际路径,在dom中插入script节点,并绑定onload事件来获取该模块加载完成的通知。
    3. 依赖script全部加载完成后,调用回调函数。
    
  4. // 定义一个模块
    define("module1", ["jquery", "./module2"], function ($, module2) {
      // 向外部导出成员,通过 return 方式实现
      return {
        start: function () {
          $("body").animate({ margin: "200px" });
          module2();
        },
      };
    });
    
    // 载入一个模块
    require(["./module1"], function (module1) {
      module1.start();
    });
    

CMD 规范(异步加载模块)

  1. CMD 对应的就是很有名的 Sea.js
  2. define(function(requireexportsmodule){
      // 通过 require 引入依赖
      var $ = require('jquery')
      // 通过 exports 或者 module.exports 对外暴露成员
      module.exports = function () {
        console.log('module 2~')
        $('body').append('<p>module2</p>')
      }
    })
    

UMD 规范

  1. UMD 通用模块定义规范(Universal Module Definition),是 CommonJS 和 AMD 的糅合
  2. UMD 先判断是否支持 Node.js 的模块(exports)是否存在,存在则使用 Node.js 模块模式;在判断是否支持 AMD(define)是否存在,存在则使用 AMD 方式加载模块

ES Modules 规范

  1. ES Modules 模块设计思想:尽量的静态化、使得编译时就能确定模块的依赖关系,以及输入和输出的变量(CommonJS 和 AMD 模块,都只能在运行时确定这些东西)