这篇“js模块化CommonJS、AMD、UMD、CMD和ES6规范是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“js模块化CommonJS、AMD、UMD、CMD和ES6规范是什么”文章吧。
模块化
模块化开发是一种管理方式,一种生产方式,也是一种解决问题的方案。一个模块就是实现某个特定功能的文件,我们可以很方便的使用别人的代码,想要什么模块,就引入那个模块。但是模块开发要遵循一定的规范,后面就出现了我们所熟悉的一系列规范。
1. CommonJS 规范
CommonJS主要用在
node开发上,每个文件就是一个模块,每个文件都有自己的一个作用域。通过
module.exports暴露
public成员。
此外,
CommonJS通过
require引入模块依赖,
require函数可以引入
node的内置模块、自定义模块和
npm等第三方模块。
定义模块:
// 定义模块 math.js var basicNum = 0; function add(a, b) { return a + b; } // 在这里写上需要向外暴露的函数、变量 module.exports = { add: add, basicNum: basicNum }
加载模块:
// 引入 math.js 模块 var math = require('./math'); math.add(2, 3); // 5
优点:
简单并且容易使用
服务器端模块便于重用
缺点:
同步的模块加载方式不适合在浏览器环境中
不能非阻塞的并行加载多个模块
2. AMD 规范
AMD是 (Asynchronous Module Definition) 的缩写,意思就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
在
AMD规范中,我们使用
define定义模块,使用
require加载模块,但是不同于
CommonJS,它要求两个参数:
定义模块:
define(id?, dependencies?, factory);
id是定义的模块名,这个参数是 可选的,如果没有定义该参数,模块名字应该默认为模块加载器请求的指定脚本的名字,如果有该参数,模块名必须是顶级的绝对的。
dependencies是定义的模块中所依赖的 模块数组,也是 可选的,依赖模块优先级执行,并且执行结果按照数组中的排序依次以参数的形式传入
factory。
factory是模块初始化要执行的函数或对象,是 必需的。
加载模块:
require([module], callback);
第一个参数
module,是一个数组,里面的成员就是要加载的模块;第二个参数
callback,则是加载成功之后的回调函数。如果将前面的
CommonJS改写成
AMD形式,就是下面这样:
require(['./math'], function (math) { math.add(2, 3); });
优点:
适合在浏览器环境中异步加载模块
可以并行加载多个模块
缺点:
提高了开发成本
不符合通用的模块化思维方式
3. UMD 规范
UMD是 (Universal Module Definition) 通用模块定义 的缩写。
UMD是
AMD和
CommonJS的一个糅合。
AMD是浏览器优先,异步加载;
CommonJS是服务器优先,同步加载。
既然要通用,怎么办呢?那就先判断是否支持
node的模块,支持就使用
node;再判断是否支持
AMD,支持则使用
AMD的方式加载。这就是所谓的
UMD。
示例:
(function (window, factory) { if (typeof exports === "object") { // CommonJS module.exports = factory(); } else if (typeof define === "function" && define.amd) { // AMD define(factory); } else { // 浏览器全局定义 window.eventUtil = factory(); } })(this, function () { // do something });
4. CMD 规范
CMD是 (Common Module Definition) 公共模块定义 的缩写。
CMD可能是在
CommonJS之后抽象出来的一套模块化语法定义和使用的标准。
在
CMD规范中,一个模块就是一个文件。
定义模块:
define(factory);
define接收
factory参数,它可以是一个函数,也可以是一个对象或一个字符串。
当
factory是一个对象或是一个字符串时,表示该模块的接口就是这个对象或者字符串。
当
factory是一个函数时,表示是该模块的构造方法。执行该构造方法,可以得到模块向外提供的接口。
factory在执行时,默认传入三个参数:
require、
exports、
module。其中
require用来加载其它模块,
exports用来向外提供模块接口。
module是一个对象,存储着与当前模块相关联的一些属性和方法。
加载模块:
我们可以通过
SeaJs的
use方法加载模块:
seajs.use([module], callback);
优点:可以很容易在
node中运行
缺点:依赖
SPM打包,模块的加载逻辑偏重
5. ES6 模块化
ES6模块的设计思想是尽量的 静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
CommonJS和
AMD模块,都只能在运行时确定这些东西。
在
ES6中,我们使用
export关键字来导出模块,使用
import关键字来引入模块。
引入模块:
// ES6模块 import { stat, exists, readFile } from 'fs';
上面代码实质是从
fs模块中加载 3 个方法,其他方法不加载。这种加载称为 “编译时加载” 或者 静态加载,即
ES6可以在编译时就完成模块加载,效率要比
CommonJS模块的加载方式高。当然,这也导致了没法引用
ES6模块本身,因为它不是对象。
导出模块:
let firstName = 'Zhou'; let lastName = 'ShuYi'; let year = 1994; export { firstName, lastName, year };
上面代码在
export后面,使用大括号指定所要输出的一组变量。
export除了输出变量,还可以输出函数或类。
优点:容易进行静态分析
缺点:原生浏览器端还没有实现该标准
AMD 和 CMD 的区别
对于依赖的模块,
AMD是 提前执行,
CMD是 延迟执行。
AMD推崇 依赖前置,
CMD推崇 依赖就近。
AMD的 API 默认是一个当多个用,
CMD的 API 严格区分,推崇职责单一。
ES6 模块与 CommonJS 模块的差异
CommonJS模块输出的是一个 值的拷贝,
ES6模块输出的是 值的引用。
CommonJS模块是运行时加载,
ES6模块是编译时输出接口。
CommonJS模块的
require()是 同步加载 模块,
ES6模块的
import命令是 异步加载,有一个独立的模块依赖的解析阶段。