记录一篇。先说结论,对于前端必须清楚。然后说明。
结论
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
- CommonJS 模块输出的是一个值的拷贝,ES6 module输出的是值的引用。
- CommonJS 模块的require()是同步加载模块,ES6 module的import命令是异步加载,有一个独立的模块依赖的解析阶段。
- import不支持动态加载,不能在if等判断语句中使用。ES2020提案 引入export ()函数export ()函数,支持动态加载模块。export ()函数可以用在任何地方,不仅仅是模块,非模块的脚本也可以使用。export ()函数与所加载的模块没有静态连接关系,这点与export 语句不相同。export ()更类似于 Node 的require方法(CommonJS的具体实现),区别主要是。Node 的require方法是同步加载,export ()函数异步加载。
CommonJS 模块
let { stat, exists, readfile } = require('fs');
// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;
上面代码的实质是整体加载fs模块(即加载的fs所有方法),生成一个对象(_fs),然后再从这个对象上面读取 3 个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”。 CommonJS 模块输出的是值的缓存,不存在动态更新,
ES6 模块
- ES6 模块是编译时加载.能做“静态优化”。export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。
- export 命令会被 JavaScript 引擎静态分析,先于模块内的其他语句执行(export 命令叫做“连接” binding 其实更合适)。不能在if等判断语句中使用。
- export命令输入的变量都是只读的,因为它的本质是输入接口。也就是说,不允许在加载模块的脚本里面,改写接口。
import {a} from './xxx.js'
a = {}; // Syntax Error : 'a' is read-only
export命令具有提升效果,会提升到整个模块的头部,首先执行。
为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。可以用任意名称指向export-default.js输出的方法,这时就不需要知道原模块输出的函数名。需要注意的是,这时export 命令后面,不使用大括号。
// export-default.js
export default function () {
console.log('foo');
}
// import-default.js
import customName from './export-default';
customName(); // 'foo'
export default命令其实只是输出一个叫做default的变量,所以它后面不能跟变量。
// modules.js
function add(x, y) {return x * y;}
export {add as default};
// 等同于
export default add;
// app.js
import { default as foo } from 'modules';
// 等同于
import foo from 'modules';
// 正确
export var a = 1;
// 正确
var a = 1;
export default a;
// 错误
export default var a = 1;
ps: umd
一种兼容 cjs 与 amd 的模块,既可以在 node/webpack 环境中被 require 引用,也可以在浏览器中直接用 CDN 被 script.src 引入
(function (root, factory) {
if (typeof define === "function" && define.amd) {
// AMD
define(["jquery"], factory);
} else if (typeof exports === "object") {
// CommonJS
module.exports = factory(require("jquery"));
} else {
// 全局变量
root.returnExports = factory(root.jQuery);
}
})(this, function ($) {
// ...
});
更多内容参看阮一峰老师的es6入门 es6.ruanyifeng.com/#docs/modul…