В синтаксисе импорта ES6, как именно оценивается модуль?

Допустим, у нас есть четыре модуля: A, B, C и D.

В модуле A:

console.log("A evaluated")
function AClass {
  console.log("A constructor")
}
var aObj = new AClass()
export default aObj;

В модуле B:

import aObj from A
export default "B"

В модуле C:

import aObj from A
export default "C"

В модуле D:

import b from B
import c from C
import aObj from A

Итак, когда модуль D оценивается, сколько раз A evaluated и A constructor будут напечатаны в консоли?

Описано ли это поведение в стандарте ES6? Что мне делать, если я хочу, чтобы модуль оценивался ТОЛЬКО ОДИН РАЗ, независимо от того, сколько раз он импортировался прямо или косвенно? У кого-нибудь есть идеи по этому поводу?


person Hanfei Sun    schedule 12.04.2016    source источник
comment
Просто говорю, что вы не должны экспортировать экземпляры, вы всегда должны экспортировать класс - или, если вам нужны только объекты, вы не должны использовать классы.   -  person Bergi    schedule 12.04.2016
comment
@Bergi Спасибо, но что мне делать, если мне нужен внешний глобальный одноэлементный экземпляр в разных модулях ... Может быть, экспорт экземпляров - единственный способ ..   -  person Hanfei Sun    schedule 12.04.2016
comment
Вы можете использовать простые литералы объектов для создания синглетонов. Нет необходимости в classes.   -  person Bergi    schedule 12.04.2016


Ответы (1)


Когда модуль D будет выполнен, консоль выведет это сообщение:

A evaluated
A constructor

Это означает, что модуль A оценивался только один раз, даже если он несколько раз импортировался другими модулями.

Правила оценки для формата ES6 modules такие же, как и для формата commonjs:

  • Модуль — это фрагмент кода, который выполняется после загрузки. Это означает, что если модуль не входит в основной комплект, он не будет оцениваться.
  • Модули являются синглтонами. Если модуль импортируется несколько раз, существует только один instance из него, и он оценивается только один раз при загрузке.

Поведение импорта одного и того же экземпляра модуля описано HostResolveImportedModule раздела спецификации ECMAScript 6.
В нем упоминается:

Эта операция (операция импорта) должна быть идемпотентной, если она завершается нормально. Каждый раз, когда он вызывается с определенным referenceModule, пара спецификаторов (import ‹a› from ‹source›) в качестве аргументов должна возвращать один и тот же экземпляр записи модуля.

Поведение однократной оценки модуля описано в ModuleEvaluation, точки 4 и 5 с использованием логического флага Evaluated.
Каждый модуль имеет флаг Evaluated, который гарантирует выполнение кода модуля только один раз.

person Dmitri Pavlutin    schedule 12.04.2016
comment
Там ничего нет о другом указанном относительном импорте. Можно рассматривать как разные источники. - person Erik Aronesty; 13.07.2020