Есть ли разница между "export default x" и " export {x as default}"?

Я понимаю, что при экспорте модуля ES6 происходит привязка между экспортируемым и импортируемым, так что при изменении экспортируемой переменной импортируемая переменная будет демонстрировать это изменение.

однако я также читал, что импортированная переменная несет привязку к экспортированной переменной только в определенных обстоятельствах.

мой конкретный вопрос заключается в том, есть ли разница в том, как экспортированные переменные связаны в следующих двух вариант развития событий...

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

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

2 ответов


они не одинаковы в общем случае, хотя они могут вести себя одинаково в случае функций и классов.

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

будет экспортировать живые привязки для переменных 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};

Как говорится в:

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

там нет спецификации о разнице в производительности, хотя.