Претензия, которую я сделал в отношении неосознанного JS, неспособного поддерживать взаимную рекурсию, является лишь догадкой для иллюстративных целей. Он разработан, чтобы помочь понять, что язык должен знать о переменных, доступных в области (областях). Это не рецепт для точного языкового поведения.
Языковая функция, такая как подъем - на самом деле подъем не существует, это всего лишь метафора для переменных, объявленных в области окружения заблаговременно во время компиляции, перед исполнением - такая фундаментальная характеристика, что она не может легко следует рассуждать о том, когда они отделены от остальных характеристик языка.
Более того, невозможно полностью проверить эту гипотезу только в JS. Фрагмент в OP использует только часть уравнения, а именно, что он использует выражения функций вместо деклараций функций, чтобы избежать подъема функции.
Язык, который я использовал для сравнения, представляет собой C, который, например, требует, чтобы сигнатуры функций объявлялись в .h заголовочных файлах, чтобы компилятор знал, как выглядит функция, даже если она не «увидела», это еще. Без него компилятор задыхается. Это своего рода ручное поднятие в некотором смысле. C делает это для проверки типов, но можно представить, что это требование существует по другим причинам, кроме этого.
Другой способ думать об этом, является ли JS является компилируемый язык, где было обнаружено все, прежде чем он выполняет, или это интерпретируется ли сверху вниз в один проход.
Если JS интерпретировался по принципу «сверху вниз», и он получил определение функции a()
, которая ссылалась на b()
внутри нее, что она еще не видела, это может быть проблемой. Если это выражение вызова было обработано без лени, в тот момент двигатель не мог понять, что будет с вызовом b()
, потому что b()
еще не обработан. Некоторые языки ленивы, а некоторые не ленивы.
Как и прежде, JS скомпилирован перед выполнением, поэтому двигатель открыл все функции (например, «подъем») перед запуском любого из них. JS также рассматривает выражения как ленивые, поэтому вместе это объясняет, почему взаимная рекурсия работает нормально.
Но если у JS нет подъема и/или не было ленивым, можно представить, что двигатель JS не сможет обрабатывать взаимную рекурсию, поскольку круговая ссылка между a()
и b()
на самом деле означает, что один из двух всегда был объявлен "слишком поздно".
Это действительно все, что я имел в виду в книге.
второй будет выдавать ошибку, если 'a (1)' вызывается перед определениями функций. – gurvinder372
Да, но это тривиально верно для любой функции и ее вызова (как я отмечаю в вопросе). Требование Симпсона, похоже, состоит в том, что для взаимной рекурсивной структуры функций требуется подъем, но это, похоже, не так. – rswerve
В первом случае, если вы дадите 'a (1)' перед определением функции, это не даст такой же ошибки. – gurvinder372