NodeJS это интерпретатор или компилятор?

Если учитывать, что он работает на движке V8, который выполняет компиляцию JavaScript в машинный код, то это компилятор.

Но данные в интернете (статьи на хабре/вопрос-ответы на хабре/другие сайты) говорят иначе: либо строго интепретатор, либо компилятор и интепретатор одновременно (разве такое может быть?).

После вышесказанного я не понимаю, можно ли с полной уверенностью назвать NodeJS компилятором?


Ответы (3 шт):

Автор решения: AivanF.

Давайте разберём по пунктам:

  • Node.js – это рантайм, среда выполнения для программ на языке JavaScript, который содержит в себе движок V8.
  • V8 – это интерпретатор языка JavaScript с технологией JIT, Just-in-Time компиляции и VM, виртуальная машина, на которой полученный байт-код выполняется. Однако это в первую очередь интерпретатор, компиляция в машинный код происходит на лету, не формируется самодостаточного бинарного/байтового файла, который можно отдельно запускать вне V8 и рантайма, куда он встраивается, будь то Node.js или браузер.
  • Можно сравнить с языком Java, программы на котором схоже обрабатывается и переводится в байт-код, однако этот процесс называется именно компиляцией, т.к полученный файл хотя запускается только лишь на JVM, виртуальной машине Джавы, однако более не требует исходного кода для работы. В принципе, аналогично можно было бы сделать и для JS, но он для этого не предназначен.
  • Более того, JiT компиляция работает хитрым способом, предназначенным для языков со слабой и динамической типизацией – в процессе работы программы, анализируются используемые типы аргументов функций, и при должной статистике, части кода перекомпилируются под конкретные типы параметров, для повышения производительности (в V8 эти подходы называются Ignition и TurboFan). Согласитесь, это явно не классическая компиляция, где мы единожды получаем выходную программу и статически её выполняем в неизменном виде :)
  • Ещё обращу внимание, может кто не в курсе, сами языки не бывают компилируемыми или интерпретируемыми, ведь языки программирования это абстрактные наборы правил, и в теории любому языку можно разработать и интерпретатор, и компилятор, правда с разными усилиями, в зависимости от количества абстракций в спецификации языка.

Подробнее про режимы JiT компиляции

Понятнее будет объяснить через хронологию выполнения кода:

Изначально, при выполнении какого-то JS кода, сперва он транслируется в не-оптимизированный, но универсальный байт-код. Этот байт-код выполняется на движке V8, но работает медленно, т.к не зная о входящих типах аргументов, они все трактуются как что угодно, требуя повсеместного использования динамической диспатчеризацией, т.е резолвинге методов и операторов через словари прототипов объектов, что обеспечивает полиморфизм в условиях слабой динамической типизации.

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

Полученная новая версия байт-кода можно сказать написана на том же языке, что и прежняя, однако является более эффективной её реализацией (примерно как сортировка пузырьком и быстрая/слиянием). Новая версия байт-кода функции выполняется в том же самом процессе V8, просто заменяет прежнюю версию, и последующие обращения к функции будут эффективнее.

Кстати, стандартный интерпретатор Питона, CPython, работает аналогично первой части – он тоже транслирует исходный текст программы в байт-код. Также существует альтернативная имплементация, которая содержит JIT компиляцию: PyPy

→ Ссылка
Автор решения: Qwertiy

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

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

Если не ошибаюсь, для языков, исполняющих промежуточный байткод (джава и C#) этот исполнитель вообще принято называть виртуальной машиной. Но поскольку в js на вход попадает исходный код, а не промежуточный, я за интерпретатор.

→ Ссылка
Автор решения: Stanislav Volodarskiy

Как вы правильно заметили Node.js использует V8:

Node.js runs on the V8 JavaScript engine...

А V8 основан на интерпретаторе и компиляторе:

In 2017, V8 shipped a brand-new compiler pipeline, consisting of Ignition (the interpreter) and TurboFan (the optimizing compiler).

Причём TurboFan настоящий оптимизирующий компилятор с кодогенерацией, распределением регистров и прочими атрибутами "нормальных" компиляторов, вроде C и C++.

→ Ссылка