export
export
声明用于从JavaScript模块导出值。导出的值随后可以使用import
声明或动态导入导入到其他程序中。导入绑定的值可能会在导出它的模块中发生变化——当模块更新其导出的绑定的值时,更新将在其导入的值中可见。
为了在源文件中使用export
声明,运行时必须将该文件解释为模块。在HTML中,这是通过在<script>
标签中添加type="module"
,或通过被另一个模块导入来完成的。模块在严格模式下自动解释。
语法
// Exporting declarations
export let name1, name2/*, … */; // also var
export const name1 = 1, name2 = 2/*, … */; // also var, let
export function functionName() { /* … */ }
export class ClassName { /* … */ }
export function* generatorFunctionName() { /* … */ }
export const { name1, name2: bar } = o;
export const [ name1, name2 ] = array;
// Export list
export { name1, /* …, */ nameN };
export { variable1 as name1, variable2 as name2, /* …, */ nameN };
export { variable1 as "string name" };
export { name1 as default /*, … */ };
// Default exports
export default expression;
export default function functionName() { /* … */ }
export default class ClassName { /* … */ }
export default function* generatorFunctionName() { /* … */ }
export default function () { /* … */ }
export default class { /* … */ }
export default function* () { /* … */ }
// Aggregating modules
export * from "module-name";
export * as name1 from "module-name";
export { name1, /* …, */ nameN } from "module-name";
export { import1 as name1, import2 as name2, /* …, */ nameN } from "module-name";
export { default, /* …, */ } from "module-name";
export { default as name1 } from "module-name";
描述
每个模块可以有两种不同类型的导出,命名导出和默认导出。每个模块可以有多个命名导出,但只有一个默认导出。每种类型对应于上述语法之一。
命名导出
// export features declared elsewhere
export { myFunction2, myVariable2 };
// export individual features (can export var, let,
// const, function, class)
export let myVariable = Math.sqrt(2);
export function myFunction() {
// …
}
在export
关键字之后,可以使用let
、const
和var
声明,以及函数或类声明。还可以使用export { name1, name2 }
语法导出在其他地方声明的名称列表。请注意,export {}
不会导出空对象——这是一个不执行任何操作的声明,不导出任何内容(空名称列表)。
导出声明不受时间死区规则的影响。可以在声明名称X
本身之前声明模块导出X
。
export { x };
const x = 1;
// This works, because `export` is only a declaration, but doesn't
// utilize the value of `x`.
默认导出
// export feature declared elsewhere as default
export { myFunction as default };
// This is equivalent to:
export default myFunction;
// export individual features as default
export default function () { /* … */ }
export default class { /* … */ }
注意:导出声明的名称必须彼此不同。具有重复名称的导出或使用多个default
导出将导致SyntaxError
并阻止模块被评估。
export default
语法允许任何表达式。
export default 1 + 1;
作为特例,函数和类被导出为声明,而不是表达式,并且这些声明可以是匿名的。这意味着函数将被提升。
// Works because `foo` is a function declaration,
// not a function expression
foo();
export default function foo() {
console.log("Hi");
}
// It's still technically a declaration, but it's allowed
// to be anonymous
export default function () {
console.log("Hi");
}
当需要导出多个值时,命名导出很有用。导入此模块时,命名导出必须使用完全相同的名称引用(可以选择使用as
重命名),但默认导出可以使用任何名称导入。例如
// file test.js
const k = 12;
export default k;
// some other file
import m from "./test"; // note that we have the freedom to use import m instead of import k, because k was default export
console.log(m); // 12
还可以重命名命名导出以避免命名冲突
export { myFunction as function1, myVariable as variable };
可以通过使用字符串字面量将名称重命名为不是有效标识符的内容。例如
export { myFunction as "my-function" };
重新导出/聚合
模块还可以“中继”从其他模块导出的值,而无需编写两个单独的导入/导出语句。这在创建集中来自各种模块的各种导出的单个模块(通常称为“桶模块”)时通常很有用。
这可以通过“export from”语法实现
export { default as function1, function2 } from "bar.js";
这类似于导入和导出的组合,只是function1
和function2
在当前模块中不可用
import { default as function1, function2 } from "bar.js";
export { function1, function2 };
大多数“import from”语法都有“export from”对应项。
export { x } from "mod";
export { x as v } from "mod";
export * as ns from "mod";
还有export * from "mod"
,尽管没有import * from "mod"
。这将mod
的所有命名导出重新导出为当前模块的命名导出,但不会重新导出mod
的默认导出。如果有两个通配符导出语句隐式地重新导出相同的名称,则这两个语句都不会重新导出。
// -- mod1.js --
export const a = 1;
// -- mod2.js --
export const a = 3;
// -- barrel.js --
export * from "./mod1.js";
export * from "./mod2.js";
// -- main.js --
import * as ns from "./barrel.js";
console.log(ns.a); // undefined
尝试直接导入重复名称将引发错误。
import { a } from "./barrel.js";
// SyntaxError: The requested module './barrel.js' contains conflicting star exports for name 'a'
尽管有其导入等价物,但以下语法无效
export DefaultExport from "bar.js"; // Invalid
执行此操作的正确方法是重命名导出
export { default as DefaultExport } from "bar.js";
“export from”语法允许省略as
标记,这使得默认导出仍然被重新导出为默认导出。
export { default, function2 } from "bar.js";
export from
支持import
支持的所有功能——例如,导入属性
export { default } from "./data.json" with { type: "json" };
示例
使用命名导出
在模块my-module.js
中,可以包含以下代码
// module "my-module.js"
function cube(x) {
return x * x * x;
}
const foo = Math.PI + Math.SQRT2;
const graph = {
options: {
color: "white",
thickness: "2px",
},
draw() {
console.log("From graph draw function");
},
};
export { cube, foo, graph };
然后在包含在HTML页面中的顶级模块中,可以有
import { cube, foo, graph } from "./my-module.js";
graph.options = {
color: "blue",
thickness: "3px",
};
graph.draw(); // Logs "From graph draw function"
console.log(cube(3)); // 27
console.log(foo); // 4.555806215962888
需要注意以下几点
使用默认导出
如果要导出单个值或为模块提供备用值,可以使用默认导出
// module "my-module.js"
export default function cube(x) {
return x * x * x;
}
然后,在另一个脚本中,导入默认导出非常简单
import cube from "./my-module.js";
console.log(cube(3)); // 27
使用export from
让我们举一个具有以下层次结构的例子
childModule1.js
:导出myFunction
和myVariable
childModule2.js
:导出MyClass
parentModule.js
:充当聚合器(并且不执行其他任何操作)- 顶级模块:使用
parentModule.js
的导出
使用代码片段,如下所示
// In childModule1.js
function myFunction() {
console.log("Hello!");
}
const myVariable = 1;
export { myFunction, myVariable };
// In childModule2.js
class MyClass {
constructor(x) {
this.x = x;
}
}
export { MyClass };
// In parentModule.js
// Only aggregating the exports from childModule1 and childModule2
// to re-export them
export { myFunction, myVariable } from "childModule1.js";
export { MyClass } from "childModule2.js";
// In top-level module
// We can consume the exports from a single module since parentModule
// "collected"/"bundled" them in a single source
import { myFunction, myVariable, MyClass } from "parentModule.js";
规范
规范 |
---|
ECMAScript语言规范 # sec-exports |
浏览器兼容性
BCD表格仅在浏览器中加载
另请参阅
import
- JavaScript 模块 指南
- 深入了解 ES6:模块 在 hacks.mozilla.org (2015)
- ES 模块:卡通深度解读 在 hacks.mozilla.org (2018)
- 探索 JS,第 16 章:模块 由 Axel Rauschmayer 博士撰写