`export default x`和`export {x as default}之间有区别吗?

时间:2016-09-01 16:29:56

标签: javascript ecmascript-6 es6-modules

据我所知,使用ES6模块导出时,导出的内容与导入的内容之间会发生绑定,因此当导出的变量发生更改时,导入的变量将显示该更改。

但是,我还读到导入的变量在某些情况下只携带绑定到导出的变量。

我的具体问题是在以下两种情况下导出变量的绑定方式是否存在差异......

// Scenario #1
let a = 5;
export default a;

// Scenario #2
let a = 5;
export { a as default };

2 个答案:

答案 0 :(得分:9)

它们在一般情况下并不相同,但在函数和类的情况下它们的行为可能相同。

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

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映射到函数声明和生成器声明。

如果我们查看定义文件内变量名称映射的规范,导出名称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 {}

将导出变量fncls的实时绑定。

您也可以

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};

答案 1 :(得分:0)

如下所述:

Mozilla Docs

场景1

它用于命名导出

// module "my-module.js"
export function cube(x) {
  return x * x * x;
}
const foo = Math.PI + Math.SQRT2;
export { cube, foo };

场景2

它用于导出单个值或具有模块的后备值

// module "my-module.js"
export default function cube(x) {
  return x * x * x;
}

但是没有关于性能差异的说明。