JavaScript-Module
# JavaScript-Module
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。
比如,CommonJS 模块就是对象,输入时必须查找对象属性。
// CommonJS模块
let { stat, exists, readfile } = require('fs');
// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# export 命令
// 输出变量
// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export { firstName, lastName, year };
// 输出函数或类(class)
export function multiply(x, y) {
return x * y;
};
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
export
命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。
// 报错
export 1;
var m = 1;
export m;
// 写法一
export var m = 1;
// 写法二
var m = 1;
export {m};
// 写法三
var n = 1;
export {n as m};
// 报错
function f() {}
export f;
// 正确
export function f() {};
// 正确
function f() {}
export {f};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# import 命令
上面代码的import
命令,用于加载profile.js
文件,并从中输入变量。import
命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js
)对外接口的名称相同。
// main.js
import { firstName, lastName, year } from './profile.js';
function setName(element) {
element.textContent = firstName + ' ' + lastName;
}
1
2
3
4
5
6
2
3
4
5
6
import
命令具有提升效果,会提升到整个模块的头部,首先执行。
foo();
import { foo } from 'my_module';
1
2
3
2
3
上面的代码不会报错,因为import
的执行早于foo
的调用。这种行为的本质是,import
命令是编译阶段执行的,在代码运行之前。
# 模块的整体加载
除了指定加载某个输出值,还可以使用整体加载,即用星号(*
)指定一个对象,所有输出值都加载在这个对象上面。
import * as circle from './circle';
console.log('圆面积:' + circle.area(4));
console.log('圆周长:' + circle.circumference(14));
1
2
3
4
2
3
4
# export default 命令
// export-default.js
export default function foo() {
console.log('foo');
}
// 或者写成
function foo() {
console.log('foo');
}
export default foo;
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
第一组是使用export default
时,对应的import
语句不需要使用大括号;第二组是不使用export default
时,对应的import
语句需要使用大括号。
// 第一组
export default function crc32() { // 输出
// ...
}
import crc32 from 'crc32'; // 输入
// 第二组
export function crc32() { // 输出
// ...
};
import {crc32} from 'crc32'; // 输入
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 适用场合
按需加载
import()
可以在需要的时候,再加载某个模块。button.addEventListener('click', event => { import('./dialogBox.js') .then(dialogBox => { dialogBox.open(); }) .catch(error => { /* Error handling */ }) });
1
2
3
4
5
6
7
8
9条件加载
动态的模块路径
# 扩展
- AMD(Asynchronous Module Definition):AMD是为浏览器端开发提出的模块化规范,主要由RequireJS推广。它支持异步加载模块,依赖前置(模块的依赖需要在使用前声明),并且使用
define
和require
来定义和加载模块。 - CMD(Common Module Definition):CMD也是为浏览器端开发提出的模块化规范,主要由SeaJS推广。与AMD类似,CMD也支持异步加载模块,但它更强调就近依赖(模块的依赖可以在使用时声明),使用
define
和require
来定义和加载模块。 - CommonJS:CommonJS是为服务器端开发提出的模块化规范,主要在Node.js中使用。CommonJS使用
module.exports
导出模块,使用require
加载模块,并且支持同步加载模块。
上次更新: 2024/08/14, 04:14:33