it-swarm.com.de

Wird JavaScript vom Design interpretiert?

Ich bin vorsichtig, diese Frage zu stellen, weil sie übermäßig anspruchsvoll erscheinen könnte. Ich habe gerade JavaScript: The Definitive Guide geöffnet und es heißt auf der ersten Seite von Kapitel 1

"JavaScript ist eine dynamische, untypisierte interpretierte Programmiersprache auf hoher Ebene."

Soll ich also davon ausgehen, dass der interpretierte Teil eine Anforderung in der Sprachspezifikation ist, oder ist es irreführend zu sagen, dass die Sprache eine interpretierte Programmiersprache ist, wenn man den Unterschied zwischen einer Sprache und ihren vielen Implementierungen berücksichtigt?

Es gibt anscheinend keine statischen Compiler für JavaScript - https://stackoverflow.com/questions/1118138/is-there-a-native-machine-code-compiler-for-javascript Vielleicht ist es nur ein Reflexion davon.

75
Matt Esch

Soll ich also davon ausgehen, dass der interpretierte Teil eine Anforderung in der Sprachspezifikation ist, oder ist es irreführend zu sagen, dass die Sprache eine interpretierte Programmiersprache ist, wenn man den Unterschied zwischen einer Sprache und ihren vielen Implementierungen berücksichtigt?

EcmaScript-Sprachfreaks verwenden häufig den Begriff "ES-Interpreter", um sich auf eine Implementierung von EcmaScript zu beziehen, aber spec verwendet diesen Begriff nicht. Das Sprachübersicht beschreibt insbesondere die Sprache in interpretatorunabhängigen Begriffen:

ECMAScript ist objektbasiert: Grundlegende Sprach- und Hostfunktionen werden von Objekten bereitgestellt, und ein ECMAScript-Programm ist ein Cluster von kommunizierenden Objekten.

Daher geht EcmaScript von einer "Host-Umgebung" aus, die als Anbieter von Objektdefinitionen definiert ist, einschließlich all jener, die E/A oder andere Links zur Außenwelt zulassen, jedoch keinen Interpreter benötigen.

Die Semantik von Anweisungen und Ausdrücken in der Sprache wird in Form von Vervollständigungsspezifikation definiert, die in einem Interpreter trivial implementiert sind, aber die Spezifikation erfordert dies nicht.

8.9 Der Abschlussspezifikationstyp

Der Vervollständigungstyp wird verwendet, um das Verhalten von Anweisungen (break, continue, return und throw) zu erläutern, die nichtlokale Steuerübertragungen durchführen. Werte des Vervollständigungstyps sind Tripel des Formtyps ( Typ , Wert , Ziel ), wobei Typ einer von normalen ist, break , continue , return , oder throw , value ist ein beliebiger ECMAScript-Sprachwert oder leer und Ziel ist eine beliebige ECMAScript-Kennung oder leer .

Der Begriff „abrupte Vervollständigung“ bezieht sich auf jede Vervollständigung mit einem anderen Typ als normal .

Die nicht lokalen Steuerübertragungen können in Befehlsarrays mit Sprüngen konvertiert werden, die eine native oder Bytecode-Kompilierung ermöglichen.

"EcmaScript Engine" könnte eine bessere Möglichkeit sein, dieselbe Idee auszudrücken.


Es gibt anscheinend keine statischen Compiler für JavaScript

Das ist nicht wahr. Der V8 "Interpreter" kompiliert intern zu nativem Code, Rhino kompiliert optional zu Java Bytecode intern und verschiedene Mozilla-Interpreter ({Trace, Spider, Jager} Monkey) verwenden einen JIT-Compiler.

V8 :

V8 erhöht die Leistung, indem JavaScript vor der Ausführung zu nativem Maschinencode kompiliert wird, anstatt Bytecode auszuführen oder zu interpretieren.

Rhino :

public final void setOptimizationLevel(int optimizationLevel)

Stellen Sie die aktuelle Optimierungsstufe ein. Es wird erwartet, dass die Optimierungsstufe eine Ganzzahl zwischen -1 und 9 ist. Alle negativen Werte werden als -1 interpretiert, und alle Werte über 9 werden als 9 interpretiert. Eine Optimierungsstufe von -1 gibt an, dass der Interpretationsmodus immer so ist benutzt. Die Stufen 0 bis 9 geben an, dass Klassendateien generiert werden können. Höhere Optimierungsstufen tauschen die Leistung der Kompilierungszeit gegen die Laufzeitleistung aus. Die Optimierungsstufe kann nicht größer als -1 eingestellt werden, wenn das Optimierungspaket zur Laufzeit nicht vorhanden ist.

TraceMonkey :

TraceMonkey erweitert Mozillas JavaScript®-Engine (bekannt als „SpiderMonkey“) um die Kompilierung von nativem Code. Es basiert auf einer an der UC Irvine entwickelten Technik namens „Spurenbäume“ und baut auf Code und Ideen auf, die mit dem Tamarin Tracing-Projekt geteilt wurden. Das Nettoergebnis ist eine massive Geschwindigkeitssteigerung sowohl im Browser chrome als auch im Webseiteninhalt.

51
Mike Samuel

Das in VM verwendete V8-JavaScript Chrome enthält keinen Interpreter. Stattdessen besteht es aus zwei Compilern und kompiliert den Code im laufenden Betrieb. Einer der Compiler läuft schnell, generiert jedoch ineffizienten Code, der andere ist ein optimierender Compiler.

Ich kann verstehen, warum manche Leute dieses "Betrügen" in Betracht ziehen, da V8 jedes Mal, wenn der Code ausgeführt wird und der Benutzer V8 installiert haben muss, den Quellcode als Eingabe verwendet. Stellen Sie sich jedoch einen Compiler vor, der eine ausführbare Datei ausgibt, die einen vollständigen Interpreter und einen Bytecode enthält. Dann hätten Sie ein eigenständiges Programm. Es wäre einfach nicht sehr effizient.

21
Jørgen Fogh

Das Aufkommen von JIT-Compilern für Skriptsprachen hat die Grenze zwischen Kompilierung und Interpretation so weit verwischt, dass die Frage nicht mehr so ​​viel bedeutet. Ist es nur eine Interpretation, wenn die Engine eine Codezeile liest und sie sofort ausführt? (Shell-Skripte werden normalerweise immer noch auf diese Weise implementiert.) Ist es eine Interpretation, wenn die Engine die gesamte Datei nimmt, sie sofort zu einem Bytecode kompiliert und dann den Bytecode interpretiert? (Die Mozilla-Engine der ersten Stufe funktioniert genauso wie CPython.) Wird sie interpretiert, wenn die Engine jeweils eine Funktion analysiert und von JIT zu nativem Code kompiliert wird? Was ist mit den Engines, die die gesamte Datei zu Bytecode kompilieren und dann nach Bedarf jeweils eine Funktion JIT? (Die meisten Skript-Engines funktionieren heutzutage auf diese Weise, und die Haupt-Java VM funktioniert auch auf diese Weise, außer dass das Kompilieren in Byte-Code im Voraus erfolgt.)

Es gibt viele Schattierungen zwischen Zusammenstellung und Interpretation.

Ich denke, die nützlichste Definition für die Interpretation ist "wird der Quellcode des Programms zur Ausführungszeit ohne einen separaten Schritt vor der Zeit eingespeist". Nach dieser Definition sind alle JavaScript-Engines Interpreter. Dies ist jedoch sicherlich nicht die einzig mögliche Definition von Interpretation.

Aber ist JavaScript für die Interpretation ausgelegt? In gewisser Weise ja: Es hat eine eval -Funktion sowie den Function -Konstruktor, mit dem Sie Programmcode als Zeichenfolge angeben können, die ausgeführt wird. Die Fähigkeit, Programmcode zur Laufzeit dynamisch zu erstellen, setzt voraus, dass die Engine Quellcode interpretieren kann. Dies bedeutet jedoch nicht, dass Sie nicht alles im Voraus machen können. Selbst in einer kompilierten Sprache wie C++ und C # können Sie Quellcode verwenden, ihn im Speicher zu neuem Maschinencode kompilieren und diesen dann ausführen. Dafür gibt es sogar Bibliotheken: LLVM + Clang in C++ und das Roslyn-Projekt in C #.

Der Übermittlungsmechanismus für JavaScript ist außerdem Quellcode. Es gibt keine erkannte Bytecodeform davon. C # und Java haben ihren offiziellen Bytecode, und jeder erwartet, dass C++ als Maschinencode geliefert wird. Dies ist jedoch immer noch kein inhärenter Aspekt, wenn die Sprache nur ein dominantes Verwendungsszenario ist. Das nahe verwandte ActionScript von JavaScript in Flash wird tatsächlich als Bytecode geliefert (der Flash-Compiler kompiliert alle Skripte vor).

19
Sebastian Redl

Es gibt keine vollständig vereinbarte Definition von "interpretiert" gegenüber "kompiliert". Bei der klassischen Unterscheidung erzeugen kompilierte Sprachen eine eigenständige ausführbare Binärdatei, während interpretierte Sprachen eine bereitgestellte Laufzeit erfordern, um den Code auszuführen. Virtuelle Maschinen, Bytecode usw. verwischen die Unterscheidung.

Hier ist jedoch eine möglicherweise nützliche Definition: Eine interpretierte Sprache ist eine Sprache, in der die Standardsprachenlaufzeit Quellcode als Eingabe verwenden und ausführen kann. Nach dieser Definition werden Perl-, Python-, Ruby-, JavaScript- und Shell-Skripte und dergleichen interpretiert (selbst wenn sie Zwischenschritte wie Bytecode oder sogar nativen Code verwenden). Java, C #, C usw. sind es nicht. Und JavaScript wird per Definition interpretiert, auch wenn die Spezifikation nicht das genaue Wort verwendet.

4
JacquesB