Typoskript wird in JS übertragen. Dann gibt es Baumschütteln, "weniger" (optional) und was sonst noch im Prozess der Bereitstellung. Aber nichts dergleichen (afaik) hat etwas mit "Kompilieren" zu tun. Alles wird gebündelt und stark optimiert, aber es wird nicht wirklich kompiliert, oder?
Kompilieren bedeutet, ein in einer Sprache A geschriebenes Programm in ein in Sprache B geschriebenes semantisch äquivalentes Programm umzuwandeln, so dass die Bewertung des kompilierten Programms gemäß den Regeln der Sprache B (z. B. Interpretation mit einem Interpreter für B ) das gleiche Ergebnis liefert und das gleiche Ergebnis erzielt Die gleichen Nebenwirkungen wie bei der Bewertung des ursprünglichen Programms gemäß den Regeln der Sprache A (z. B. Interpretation mit einem Interpreter für A ).
Kompilieren bedeutet einfach, ein Programm von Sprache A in Sprache B zu übersetzen . Das ist alles was es bedeutet. (Beachten Sie auch, dass A und B durchaus dieselbe Sprache haben können.)
In einigen Fällen haben wir speziellere Namen für bestimmte Arten von Compilern, je nachdem, was A und B sind und was der Compiler tut:
- Wenn A als Assemblersprache und B als Maschinensprache wahrgenommen wird, nennen wir es Assembler .
- Wenn A als Maschinensprache und B als Assemblersprache wahrgenommen wird, nennen wir es Disassembler .
- Wenn A als niedriger als B wahrgenommen wird, nennen wir es einen Dekompiler .
- Wenn A und B dieselbe Sprache sind und das resultierende Programm auf irgendeine Weise schneller oder leichter ist, nennen wir es einen Optimierer .
- Wenn A und B die gleichen Sprachen sind und das resultierende Programm kleiner ist, nennen wir es einen Minifier .
- Wenn A und B die gleichen Sprachen sind und das resultierende Programm weniger lesbar ist, nennen wir es einen Verschleierer .
- Wenn A und B ungefähr auf der gleichen Abstraktionsebene wahrgenommen werden, nennen wir es einen Transpiler , und
- Wenn A und B als ungefähr auf derselben Abstraktionsebene wahrgenommen werden und das resultierende Programm Formatierungen, Kommentare und Programmiererabsichten beibehält, so dass es möglich ist, das resultierende Programm auf dieselbe Weise wie das ursprüngliche Programm beizubehalten, rufen wir auf Es ist ein Re-Engineering-Tool .
Beachten Sie auch, dass ältere Quellen möglicherweise die Begriffe "Übersetzung" und "Übersetzer" anstelle von "Kompilierung" und "Compiler" verwenden. Zum Beispiel spricht C von "Übersetzungseinheiten".
Sie können auch über den Begriff "Sprachprozessor" stolpern. Dies kann je nach Definition entweder einen Compiler, einen Interpreter oder sowohl Compiler als auch Interpreter bedeuten.
Javascript selbst wird immer noch interpretiert, oder?
JavaScript ist eine Sprache. Sprachen sind eine Reihe von logischen Regeln und Einschränkungen. Sprachen werden nicht interpretiert oder kompiliert. Sprachen gerade sind .
Zusammenstellung und Interpretation sind Merkmale eines Compilers oder Interpreters (duh!). Jede Sprache kann mit einem Compiler implementiert werden und jede Sprache kann mit einem Interpreter implementiert werden. Viele Sprachen haben sowohl Compiler als auch Interpreter. Viele moderne Hochleistungs-Ausführungs-Engines haben sowohl mindestens einen Compiler als auch mindestens einen Interpreter.
Diese beiden Begriffe gehören zu verschiedenen Abstraktionsebenen. Wenn Englisch eine getippte Sprache wäre, wäre "interpretierte Sprache" ein Tippfehler.
Beachten Sie auch, dass einige Sprachen weder einen Interpreter noch einen Compiler haben. Es gibt Sprachen, die überhaupt keine Implementierung haben. Trotzdem sind sie Sprachen, und Sie können Programme in ihnen schreiben. Sie können sie einfach nicht ausführen.
Beachten Sie auch, dass alles irgendwann interpretiert wird : Wenn Sie etwas ausführen möchten, müssen Sie es interpretieren. Die Kompilierung übersetzt nur Code von einer Sprache in eine andere. Es läuft nicht. Deutung läuft es. (Wenn ein Interpreter in Hardware implementiert ist, nennen wir ihn manchmal "CPU", aber es ist immer noch ein Interpreter.)
Ein typisches Beispiel: Jede einzelne derzeit vorhandene Mainstream-JavaScript-Implementierung verfügt über einen Compiler.
V8 begann als reiner Compiler: Es kompilierte JavaScript direkt zu mäßig optimiertem nativem Maschinencode. Später wurde ein zweiter Compiler hinzugefügt. Jetzt gibt es zwei Compiler: einen kompakten Compiler, der mäßig optimierten Code erzeugt, aber der Compiler selbst ist sehr schnell und benötigt wenig RAM. Dieser Compiler fügt auch Profilierungscode in den kompilierten Code ein. Der zweite Compiler ist ein schwererer, langsamerer und teurerer Compiler, der jedoch viel engeren, viel schnelleren Code erzeugt. Außerdem werden die Ergebnisse des vom ersten Compiler eingefügten Profilierungscodes verwendet, um dynamische Optimierungsentscheidungen zu treffen. Außerdem wird die Entscheidung, welcher Code mit dem zweiten Compiler neu kompiliert werden soll, basierend auf diesen Profilinformationen getroffen. Beachten Sie, dass zu keinem Zeitpunkt ein Dolmetscher beteiligt ist. V8 interpretiert nie, es wird immer kompiliert. Tut es nicht' Es enthält nicht einmal einen Dolmetscher. (Eigentlich glaube ich heutzutage, ich beschreibe die ersten beiden Iterationen.)
SpiderMonkey kompiliert JavaScript zu SpiderMonkey-Bytecode, den es dann interpretiert. Der Interpreter profiliert auch den Code, und dann wird der Code, der am häufigsten ausgeführt wird, von einem Compiler zu nativem Maschinencode kompiliert. SpiderMonkey enthält also zwei Compiler: einen von JavaScript zu SpiderMonkey-Bytecode und einen von SpiderMonkey-Bytecode zu nativem Maschinencode.
Fast alle JavaScript-Ausführungs-Engines (mit Ausnahme von V8) folgen diesem Modell eines AOT-Compilers, der JavaScript zu Bytecode kompiliert, und einer Mixed-Mode-Engine, die zwischen dem Interpretieren und Kompilieren dieses Bytecodes umschaltet.
Sie haben in einem Kommentar geschrieben:
Ich dachte wirklich, dass Maschinencode irgendwo involviert ist.
Was bedeutet "Maschinencode" überhaupt?
Was ist die Maschinensprache eines Mannes, ist die Zwischensprache eines anderen Mannes und umgekehrt? Zum Beispiel gibt es CPUs , die JVM - Bytecode nativ ausführen kann, auf eine solche CPU, JVM - Bytecode ist nativen Maschinencode. Und es gibt Dolmetscher für x86 - Maschinencode, wenn Sie von diesem x86 Maschinencode ausgeführt werden Bytecode interpretiert.
Es gibt einen x86-Interpreter namens JPC, der in Java geschrieben ist. Wenn ich x86-Maschinencode auf einem JPC ausführe, der auf einer nativen JVM-CPU ausgeführt wird… welcher Bytecode und welcher nativer Code? Wenn ich x86-Maschinencode in JavaScript kompiliere (ja, es gibt Tools, die das können) und ihn in einem Browser auf meinem Telefon (mit einer ARM-CPU) ausführe, welcher Bytecode und welcher native Maschinencode? Was ist, wenn das Programm, das ich kompiliere, ein SPARC-Emulator ist und ich ihn zum Ausführen von SPARC-Code verwende?
Beachten Sie, dass jede Sprache eine abstrakte Maschine induziert und Maschinensprache für diese Maschine ist. Daher ist jede Sprache (einschließlich sehr hoher Sprachen) nativer Maschinencode. Sie können auch einen Dolmetscher für jede Sprache schreiben. Daher ist jede Sprache (einschließlich x86-Maschinencode) nicht muttersprachlich.