我知道在 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;
export {a};
会导出值为a
的变量,即使模块内部的a
已经改变,输出的值仍然是4
。而使用export {a as default};
则会将a
的值5
作为默认输出。ECMAScript 规范定义了三种不同形式的export default
,在这个表格中给出了一些例子:http://www.ecma-international.org/ecma-262/7.0/#table-42,在主要语法声明中也有相关内容:http://www.ecma-international.org/ecma-262/7.0/#sec-exports
export default HoistableDeclaration
export default ClassDeclaration
export default [lookahead ∉ { function, class }] AssignmentExpression;
在这种情况下,HoistableDeclaration
映射到函数声明和生成器声明。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;
}
虽然没有关于性能差异的具体规定。
export default X
与export {X as default};
之间的区别。 - loganfsmyth