模块导出 export

export 命令用于规定模块的对外接口。

导出方式

ECMAScript 规范中的模块化方案提供了两种导出模块的方式:

  • 命名导出(Named Exports)
  • 默认导出(Default Export)

命名导出

在声明的变量前添加 export 关键字即可将相对应的变量输出。

导出前声明的值:

这种写法能在脚本底部清晰看到所有输出模块,推荐。

const originModule = true;
export { originModule };

在导出时重命名:

同样使用 as 关键字,同一函数可以定义多个不同的变量名输出。

export { originModule as newModule };
export { originModule as smartModule };

声明后立即导出:

export var something = true;
export let anything = true;
export const nothing = true;
export function everything (){}
export class interesting = true;

默认导出

默认导出让开发者无须知道源模块输出的模块名称即可完成导入。(默认导出的变量无法使用命名导入)

导出一个值作为源模块的默认导出:

export default something;

⚠️ 注意: 仅当源模块只有一个导出时,才建议使用此做法。

将默认和命名导出组合在同一个模块中是不好的做法,尽管它是规范允许的。

扩展:

本质上,export default 就是输出一个叫做 default 的变量或方法,然后系统允许你为它取任意名字。

所以,下面的写法是有效的。

模块导出:

function add(x, y) {
return x * y;
}
export { add as default };
// 等同于
// export default add;

模块导入:

import { default as foo } from 'modules';
// 等同于
// import foo from 'modules';

正是因为 export default 命令其实只是输出一个叫做 default 的变量,所以它后面不能跟变量声明语句。

特性规范

对应关系

需要特别注意的是,export 命令规定的是 对外的接口,必须与模块内部的变量建立一一对应关系。

// Error
export 1
// Error
const foo = 1
export foo

如上两种写法都会报错,因为均会输出 1,而 1 只是一个值 ,并非对外的接口。

export var foo = 1;
var bar = 1;
export { bar };
var baz = 1;
export { baz as bat };

其他脚本可以通过这个接口,取到值 1。它们的实质是,在接口名与模块内部变量之间,建立了一一对应的关系。

同样地,函数和类必须遵守这种书写方法。

// Error
function foo(){}
export foo
// Good
export function bar(){}
// Good
function baz(){}
export { baz }

另外,export 语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。

模块顶层输出

export 命令可以出现在模块的任何位置,只要处于模块顶层就可以。

如果处于块级作用域内,就会报错,import 命令也是如此。这是因为处于条件代码块之中,就没法做 静态优化 了,违背了 ES6 模块的设计初衷。

function foo() {
export default 'bar';
// SyntaxError
}
foo();