我知道使用 ES6 模块导出时,导出的内容和导入的内容之间会发生绑定,因此当导出的变量发生变化时,导入的变量会显示出这种变化。
但是,我还读到导入的变量仅在某些情况下携带与导出变量的绑定。
我的具体问题是,在以下两种情况下,导出变量的绑定方式是否存在差异......
// Scenario #1
let a = 5;
export default a;
// Scenario #2
let a = 5;
export { a as default };
我知道使用 ES6 模块导出时,导出的内容和导入的内容之间会发生绑定,因此当导出的变量发生变化时,导入的变量会显示出这种变化。
但是,我还读到导入的变量仅在某些情况下携带与导出变量的绑定。
我的具体问题是,在以下两种情况下,导出变量的绑定方式是否存在差异......
// Scenario #1
let a = 5;
export default a;
// Scenario #2
let a = 5;
export { a as default };
它们在一般情况下并不相同,尽管它们在函数和类的情况下可以表现相同。
let a = 4;
export default a;
相当于
let a = 4;
let *default* = a;
export {*default* as default};
意思是
let a = 4;
export default a;
a = 5;
将4
作为导出值保留,即使a
模块内部已更改,而export {a as default};
将导出值5
。
export default
ECMAScript规范定义了三种不同的. /www.ecma-international.org/ecma-262/7.0/#sec-exports
export default HoistableDeclaration export default ClassDeclaration export default [lookahead ∉ { function, class }] AssignmentExpression;
在HoistableDeclaration
这种情况下映射到函数声明和生成器声明。
如果我们查看定义文件内变量名称映射到导出名称的规范,http://www.ecma-international.org/ecma-262/7.0/#sec-exports-static-semantics-exportentries
ExportDeclaration: export default HoistableDeclaration Let names be BoundNames of HoistableDeclaration. Let localName be the sole element of names. Return a new List containing the Record {[[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default"}. ExportDeclaration: export default ClassDeclaration Let names be BoundNames of ClassDeclaration. Let localName be the sole element of names. Return a new List containing the Record {[[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default"}. ExportDeclaration: export default AssignmentExpression; Let entry be the Record {[[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: "*default*", [[ExportName]]: "default"}. Return a new List containing entry. NOTE "*default*" is used within this specification as a synthetic name for anonymous default export values.
BoundNames
这里返回作为值传递的函数或类的名称,所以在前两种情况下
export default function fn(){}
// or
export default function* fn(){}
// or
export default class cls {}
将导出变量的实时绑定fn
或cls
.
你也可以做
export default function(){}
// or
export default function*(){}
// or
export default class {}
在这种情况下,这些将导出没有实时绑定的值,因为它们没有名称。
在 的最后一种情况下export default AssignmentExpression ;
,这就是您的示例所export default a;
满足的。你可以注意到它有[[LocalName]]: *default*
而不是[[LocalName]]: localName
像其他人一样。那是因为export default a;
不识别a
为正在导出的名称,它将其作为当前值处理为a
导出值。这与 没有什么不同export default 4;
,从规范的角度来看,它没有名称。
本质上
export default function fn(){}
相当于
function fn(){}
export {fn as default};
但
let a = 4;
export default a;
不等于:
let a = 4;
export {a as default};
如中所述:
它用于命名导出
// module "my-module.js"
export function cube(x) {
return x * x * x;
}
const foo = Math.PI + Math.SQRT2;
export { cube, foo };
它用于导出单个值或为模块提供后备值
// module "my-module.js"
export default function cube(x) {
return x * x * x;
}
但是,没有关于性能差异的规范。