Подтвердить что ты не робот

Модули ES6: импортированные константы undefined сначала; они становятся доступными позже

Я использую модули ES6 в своем приложении JavaScript. Источники скомпилированы с помощью webpack и babel. Это сокращенная версия файла, которая вызывает у меня проблемы:

export const JUST_FORM = 0;
export const AS_PAGE = 1;

console.log(AS_PAGE); // **

export default function doSomething(mode = AS_PAGE) {
  console.log(mode);
  console.log(JUST_FORM);
}

Я использую эту функциональность так же, как вы ожидали.

import doSomething, { AS_PAGE } from './doSomething'

console.log(AS_PAGE);

doSomething();

Когда я запускаю приложение, он печатает три раза undefined и только после ожидаемого значения AS_PAGE, которое является console.log, помеченным **. Однако это напечатано последним! Он показывает, что:

  • Константа AS_PAGE, когда используется как параметр по умолчанию для функции doSomething, не определяется в момент определения функции.
  • Константа JUST_FORM не определяется при вызове doSomething.
  • Константа AS_PAGE не определена при явном импорте.

По-видимому, здесь происходит то, что только экспорт default обрабатывается и оценивается, а остальная часть файла игнорируется до следующего. Я импортирую этот файл в несколько разных мест в моем приложении (который в настоящий момент довольно велик), и в какой-то момент эти значения становятся фактически доступными. Судя по выводам консоли, это вопрос времени, но вполне возможно, что у него есть другая причина. Очевидно, что я импортирую точно так же во всех местах.

В любом случае, я написал все свое приложение с предположением, что как только я что-то импортирую, он сразу же доступен, и я могу использовать его в своем коде. Я прочитал (кратко) о том, как модули ES6 должны работать, и я не нашел ничего, что могло бы доказать, что это предположение неверно. И он работает до сих пор.

Также обратите внимание, что поведение такое же, когда я запускаю его с помощью webpack-dev-server или скомпилировал его в один пакет.

Действительно ли это поведение? Что может быть причиной этого?

4b9b3361

Ответ 1

Как указано в комментариях, здесь мы получаем круговые зависимости.

В коде, представленном в вопросе, фактически нет круговой зависимости (потому что это просто упрощенный фрагмент кода), но симптомы очень ясны.

Простейшим примером циклической зависимости является то, что файл A импортирует файл B, а файл B импортирует A. К сожалению, иногда это затрудняет определение того, что круг может быть сколь угодно большим, охватывая огромное количество файлов.

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