为什么默认导出不像命名导出那样实时?
//------ lib.js ------
export let counter = 0;
export function incCounter() {
counter++;
}
export default counter;
//------ main1.js ------
import { counter, incCounter } from "./lib";
import $counter from "./lib";
console.log({ $counter, counter }); // {$counter: 0, counter: 0}
incCounter();
console.log({ $counter, counter }); // {$counter: 0, counter: 1}
这表明命名的
counter
导出已启用,但默认导出未启用。为什么?
据我所知,这纯粹是因为这是定义模块的人做出的决定,因为他们希望允许导出任意表达式的结果。
export default
之后的是 表达式,而不是绑定(除非它是函数声明或 class
声明)。例如,这是一个有效的默认导出:
export default 6 * 7;
所以你的
export default counter;
是评估counter
的值,然后导出它,而不是实时绑定。
您可以在规范的模块部分顶部的语法中看到这一点:
HoistableDeclaration[~产量,+等待,+默认]export default
类声明[~Yield,+等待,+默认]export default
[lookahead ∉ { function, async [这里没有 LineTerminator] function, class }] 赋值表达式[+In, ~Yield, +Await] ;export default
前两个覆盖函数声明和
class
声明;第三个导出 AssignmentExpression 的结果,这是您的代码正在使用的。
它可以有不同的定义,但事实并非如此。 (主观上:可能出于充分的理由,在模块的设计中投入了很多的思考。)
我怀疑希望能够导出任意表达式的结果的原因主要是使用默认导出来导出对象文字的结果:
export default {
something: "some value",
// ...
};
例如,当使用模块作为配置文件时,这很有用。
有时是的!这取决于您使用的语法。
这不是实时绑定:
export let counter = 0;
export function incCounter() {
counter++;
}
export default counter;
但这就是!
export let counter = 0;
export function incCounter() {
counter++;
}
export { counter as default };