CommonJS
CommonJS 是服务端模块的规范,Node.js采用了这个规范。
CommonJS特性
1. 一个文件就是一个模块,拥有单独的作用域。
2. CommonJS 模块输出的是一个值的拷贝。
3. CommonJS 模块是运行时加载。
4. CommonJS 模块的require()是同步加载模块。
CommonJs的使用
CommonJs通过require来加载模块,通过module.exports或者exports来暴露模块中的内容。
//lib.js
function incCounter() {
counter++;
}
module.exports = {
incCounter: incCounter,
};
//main.js
const mod = require('./lib');
console.log(mod.counter); // 3
mod.incCounter();
AMD
AMD的全称是Asynchronous Module Definition 异步加载模块, 它主要是使用在浏览器上,AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
AMD特性
1. 采用异步方式加载模块,模块的加载不影响它后面语句的运行.
2. 所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行
3. 推崇依赖前置,在定义模块的时候就要声明其依赖的模块
AMD的使用
使用require.js来实现AMD规范的模块化:用require.config()指定引用路径。用define()来定义模块用require来加载模块。
//通过数组引入依赖 ,回调函数通过形参传入依赖
define(['someModule1', ‘someModule2’], function (someModule1, someModule2) {
function foo () {
/// someing
someModule1.test();
}
return {foo: foo}
});
AMD 规范允许输出模块兼容 CommonJS 规范,这时 define 方法如下:
define(function (require, exports, module) {
var reqModule = require("./someModule");
requModule.test();
exports.asplode = function () {
//someing
}
});
CMD
CMD的全称是Common Module Definition通用模块定义,与AMD类似.不同点在于:AMD推崇依赖前置,提前执行,而CMD推崇依赖就近,延迟执行.它的使用和定义需要使用SeaJS.
CMD特性
1.采用异步方式加载模块,模块的加载不影响它后面语句的运行.
2.推崇就近依赖,只有在用到某个模块的时候再去require
CMD的使用
使用define来定义define(id?, deps?, factory)
factory:一个函数,有三个参数,function(require, exports, module)
require:一个方法,接受 模块标识 作为唯一参数,用来获取其他模块提供的接口:require(id)
exports:一个对象,用来向外提供模块接口
module:一个对象,上面存储了与当前模块相关联的一些属性和方法
// 定义模块 module.js
define(function(require, exports, module) {
var $ = require('jquery.min.js')
$('div').addClass('active');
});
// 加载模块
seajs.use(['module.js'], function(my){
});
//AMD
define(['./a','./b'], function (a, b) {
//依赖一开始就写好
a.test();
b.test();
});
//CMD
define(function (requie, exports, module) {
//依赖可以就近书写
var a = require('./a');
a.test();
...
//软依赖
if (status) {
var b = requie('./b');
b.test();
}
});
UMD
UMD的全称为Universal Module Definition,是一种javascript通用模块定义规范,让你的模块能在javascript所有运行环境中发挥作用,是跨平台的解决方案
UMD 先判断是否支持 Node.js 的模块(exports)是否存在,存在则使用 Node.js 模块模式。
再判断是否支持 AMD(define 是否存在),存在则使用 AMD 方式加载模块。
(function (window, factory) {
if (typeof exports === 'object') {
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
define(factory);
} else {
window.eventUtil = factory();
}
})(this, function () {
//module ...
});
esm
esm即ES6模块
esm特性
1. 浏览器可以直接加载ES6模块,也是使用<script>标签,但是要加入type="module"属性. <script type="module" src="./foo.js"></script>
2. ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";。
3. ES6 模块输出的是值的引用。
4. ES6 模块是编译时输出接口。
5. ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段。
esm的使用
模块功能主要由两个命令构成:export和import。export命令用于规定模块的
对外接口,import命令用于输入其他模块提供的功能.
// profile.js
var year = 1958;
export { year };
export default year;
//test.js
import { year } from './profile.js'; //对应export {}
import year from './profile.js'; //对应export default
ES6 模块与 CommonJS 模块的差异
1. CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
- CommonJS模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值
- ES6模块的运行机制与CommonJS不一样。JS引擎对脚本静态分析的时候,遇到模块加载命令import,
就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
换句话说,ES6的import有点像Unix系统的“符号连接”,原始值变了,import加载的值也会跟着变。
因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
2. CommonJS模块是运行时加载,ES6模块是编译时输出接口
- 运行时加载: CommonJS模块就是对象;即在输入时是先加载整个模块,生成一个对象,
然后再从这个对象上面读取方法,这种加载称为“运行时加载”。
- 编译时加载: ES6模块不是对象,而是通过export命令显式指定输出的代码,import时采用静态命令的形式。
即在import时可以指定加载某个输出值,而不是加载整个模块,这种加载称为“编译时加载”。
- 本文链接:http://example.com/2020/05/13/js/commonjs/
- 版权声明:本博客所有文章除特别声明外,均默认采用 许可协议。