10

我知道使用 ES6 模块导出时,导出的内容和导入的内容之间会发生绑定,因此当导出的变量发生变化时,导入的变量会显示出这种变化。

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

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

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

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

2 回答 2

11

它们在一般情况下并不相同,尽管它们在函数和类的情况下可以表现相同。

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 defaultECMAScript规范定义了三种不同的. /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};
于 2016-09-01T16:56:43.090 回答
0

如中所述:

Mozilla 文档

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

但是,没有关于性能差异的规范。

于 2016-09-01T16:48:20.467 回答