- CommonJS模块:对象,实质是运行时加载。输入时必须查找对象属性。
- ES6模块不是对象:实质是编译时加载或者静态加载。
// CommonJS模块
let { stat, exists, readFile } = require('fs');
// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;
CommonJs:
- 整体加载fs模块
- 生成一个对象(_fs)
- 从这个对象上面读取方法
ES6: 从fs模块加载这3个方法,其他方法不加载
ES6 的模块自动采用严格模式
- 一个模块就是一个独立的文件
- 文件内部的所有变量,外部无法获取
- export 接口必须与模块内部的变量建立一一对应关系
- export 接口与其对应的值是动态绑定关系
- export 必须处于模块顶层
export 1; // 错误
export var m = 1; // 正确
export function f() {}; // 正确
var m = 1;
export m; // 错误
export {m}; // 正确
function f() {}
export f; // 错误
export {f}; // 正确
// export必须处于模块顶层
function foo() {
export default 'bar' // SyntaxError
}
foo()
- 变量只读:输入的变量都是只读的
- 提升效果:会提升到整个模块的头部,首先执行
- 静态执行:不能使用表达式和变量
- 执行一次:多次重复执行同一句import语句,那么只会执行一次
// 变量只读
import {a} from './xxx.js'
a = {}; // Syntax Error : 'a' is read-only;
a.foo = 'hello'; // 合法操作
// 提升效果
foo();
import { foo } from 'my_module';
// 静态执行
import { 'f' + 'oo' } from 'my_module'; // 报错
// 报错
if (x === 1) {
import { foo } from 'module1';
} else {
import { foo } from 'module2';
}
模块整体加载所在的那个对象是可以静态分析的,不允许运行时改变。
// circle.js
export function area(radius) {
return Math.PI * radius * radius;
}
export function circumference(radius) {
return 2 * Math.PI * radius;
}
// main.js
import * as circle from './circle';
// 下面两行都是不允许的
circle.foo = 'hello';
circle.area = function () {};
本质上,export default就是输出一个叫做default的变量或方法。所以它后面不能跟变量声明语句。
export default 42; // 正确
export 42; // 报错
export var a = 1; // 正确
export default var a = 1; // 错误
var a = 1;
export default a; // 正确
export a // 错误
export { foo, bar } from 'my_module';
// 可以简单理解为
import { foo, bar } from 'my_module';
export { foo, bar };
foo和bar实际上并没有被导入当前模块,只是相当于对外转发了这两个接口,导致当前模块不能直接使用foo和bar
export * from 'circle';
export var e = 2.71828182846;
export default function(x) {
return Math.exp(x);
}
// constants/db.js
export const db = {
url: 'http://my.couchdbserver.local:5984',
admin_username: 'admin',
admin_password: 'admin password'
};
// constants/user.js
export const users = ['root', 'admin', 'staff', 'ceo', 'chief', 'moderator'];
// constants/work.js
export {db} from './db';
export {users} from './users';
// script.js
import {db, users} from './constants/index';
动态加载,相当于Node中的require。import()返回一个 Promise 对象
const main = document.querySelector('main');
import(`./section-modules/${someVariable}.js`)
.then(module => {
module.loadPageInto(main);
})
.catch(err => {
main.textContent = err.message;
});
适合场景:
- 按需加载
- 条件加载
- 动态的模块路径