缘由
在 ES6 之前, 最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。
最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。
CommonJS规范
- CommonJS模块就是对象,输入时必须查找对象属性
// CommonJS模块
let { stat, exists, readfile } = require('fs');
// 导出,两种方法任意都可以
// 方法一:
exports.myApi = myApi
exports.add = add
// 方法二
module.exports = {
myApi,
add
}
//------------
module.exports = {};
module.exports = function(){
return {name: 'Jane'};
}
//上面代码的实质是整体加载fs模块(即加载fs的所有方法),
//生成一个对象(_fs),然后再从这个对象上面读取 3 个方法。
//这种加载称为“运行时加载”,因为只有运行时才能得到这个对象
//,导致完全没办法在编译时做“静态优化”。
ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
- 由于 ES6 模块是编译时加载,使得静态分析成为可能
// ES6模块
//实质是从fs模块加载 3 个方法
import { stat, exists, readFile } from 'fs';
......
export function area(radius) {
return Math.PI * radius * radius;
}
export { stat, exists, readFile}; . . . .
//模块整体加载
import * as circle from './circle';
export default function () {
console.log('foo');
}
//export default命令用在非匿名函数前,也是可以的。
export default function foo() {
console.log('foo');
}
///其他方法不加载。这种加载称为“编译时加载”或者静态加载
除了静态加载带来的各种好处,ES6 模块还有以下好处。
- 不再需要UMD模块格式了,将来服务器和浏览器都会支持 ES6 模块格式。目前,通过各种工具库,其实已经做到了这一点。
将来浏览器的新 API 就能用模块格式提供,不再必须做成全局变量或者navigator对象的属性。
不再需要对象作为命名空间(比如Math对象),未来这些功能可以通过模块提供。
import()函数
import()函数支持动态加载模块。
- import函数的参数specifier,指定所要加载的模块的位置。import命令能够接受什么参数,import()函数就能接受什么参数
import()返回一个 Promise 对象。
import()函数可以用在任何地方,不仅仅是模块,非模块的脚本也可以使用。它是运行时执行,也就是说,什么时候运行到这一句,就会加载指定的模块。另外,import()函数与所加载的模块没有静态连接关系,这点也是与import语句不相同。
import()类似于 Node.js 的require()方法,区别主要是前者是异步加载,后者是同步加载。
由于import()返回 Promise 对象,所以需要使用then()方法指定处理函数。考虑到代码的清晰,更推荐使用await命令。
import()的一些适用场合。
//下面是import()的一些适用场合。
//(1)按需加载。
//import()可以在需要的时候,再加载某个模块。
button.addEventListener('click', event => {
import('./dialogBox.js')
.then(dialogBox => {
dialogBox.open();
})
.catch(error => {
/* Error handling */
})
});
//上面代码中,import()方法放在click事件的监听函数之中,
//只有用户点击了按钮,才会加载这个模块。
(2)条件加载
//import()可以放在if代码块,根据不同的情况,加载不同的模块。
if (condition) {
import('moduleA').then(...);
} else {
import('moduleB').then(...);
}
//上面代码中,如果满足条件,就加载模块 A,否则加载模块 B。
//(3)动态的模块路径
//import()允许模块路径动态生成。
import(f()).then(...);
//上面代码中,根据函数f的返回结果,加载不同的模块。