私はこの質問をするのは慎重すぎるようです。 JavaScript:The Definitive Guideを開いたところ、第1章の最初のページが示されています
「JavaScriptは、高レベルで動的な型なしのインタプリタ型プログラミング言語です」
それで、解釈された部分は言語仕様の要件であると解釈しますか、それとも、言語とその多くの実装の違いを尊重するとき、言語は解釈されたプログラミング言語であると誤解を招きますか?
JavaScript用の静的コンパイラーはありません- https://stackoverflow.com/questions/1118138/is-there-a-native-machine-code-compiler-for-javascript たぶんそれは単なるこれの反映。
それで、解釈された部分は言語仕様の要件であると解釈しますか、それとも、言語とその多くの実装の違いを尊重するとき、その言語は解釈されたプログラミング言語であると誤解していますか?
EcmaScript言語のマニアは、「ESインタプリタ」という用語を使用してEcmaScriptの実装を指すことがよくありますが、 spec はその用語を使用しません。 言語の概要 は、特に言語をインタープリターに依存しない用語で説明します。
ECMAScriptはオブジェクトベースです。基本言語とホスト機能はオブジェクトによって提供され、ECMAScriptプログラムは通信オブジェクトのクラスターです。
したがって、EcmaScriptは、「ホスト環境」を想定しています。これは、I/Oまたは他の外部へのリンクを許可するすべてのオブジェクト定義のプロバイダーとして定義されていますが、インタープリターは必要ありません。
言語のステートメントと式のセマンティクスは、インタプリタで簡単に実装される 完了指定 の観点から定義されていますが、仕様ではこれは必須ではありません。
8.9完了仕様タイプ
完了タイプは、制御の非ローカル転送を実行するステートメント(
break
、continue
、return
およびthrow
)の動作を説明するために使用されます。完了タイプの値は、(type、value、target)、ここでtypeはnormal、のいずれかですbreak、continue、return 、またはthrow、valueはECMAScript言語の値または empty、およびtargetはECMAScript識別子またはemptyです。「突然の補完」という用語は、normal以外のtypeによる補完を指します。
ローカル以外の制御の転送は、ネイティブまたはバイトコードのコンパイルを可能にするジャンプを含む命令の配列に変換できます。
"EcmaScript Engine" は、同じアイデアを表現するためのより良い方法かもしれません。
どうやらJavaScript用の静的コンパイラはありません
本当じゃない。 V8の「インタープリター」は内部でネイティブコードにコンパイルされ、RhinoはオプションでJavaバイトコード内部にコンパイルされ、さまざまなMozillaインタープリター({Trace、Spider、Jager} Monkey)はJITコンパイラーを使用します。
V8 :
V8は、バイトコードを実行したり解釈したりするのではなく、JavaScriptを実行する前にネイティブマシンコードにコンパイルすることでパフォーマンスを向上させます。
サイ :
public final void setOptimizationLevel(int optimizationLevel)
現在の最適化レベルを設定します。最適化レベルは-1から9までの整数であることが期待されます。負の値は-1と解釈され、9より大きい値は9と解釈されます。最適化レベル-1は、解釈モードが常に中古。 レベル0から9は、クラスファイルが生成される可能性があることを示します。最適化レベルを高くすると、コンパイル時のパフォーマンスと実行時のパフォーマンスがトレードオフになります。実行時にオプティマイザパッケージが存在しない場合、オプティマイザレベルを-1より大きく設定することはできません。
TraceMonkeyは、MozillaのJavaScript®エンジン(「SpiderMonkey」として知られています)にネイティブコードのコンパイルを追加します。 UCアーバインで開発された「トレースツリー」と呼ばれる手法に基づいており、Tamarin Tracingプロジェクトと共有されているコードとアイデアに基づいています。最終的に、ブラウザchrome=とWebページコンテンツの両方で速度が大幅に向上します。
V8 JavaScript VMで使用されるChromeにはインタープリターが含まれていません。代わりに、2つのコンパイラーで構成され、その場でコードをコンパイルします。コンパイラーの1つ高速に実行されますが、非効率的なコードが生成されます。もう1つは最適化コンパイラです。
V8はコードが実行されるたびにソースコードを入力として受け取り、ユーザーがV8をインストールする必要があるため、一部の人々がこの「不正行為」を検討する理由を理解できます。ただし、完全なインタープリターとバイトコードを含む実行可能ファイルを生成するコンパイラーを検討してください。次に、スタンドアロンのプログラムを作成します。それは非常に効率的ではありません。
スクリプト言語用のJITコンパイラの出現により、コンパイルと解釈の境界が曖昧になり、質問がそれほど意味を持たなくなった。エンジンがコード行を読み取ってすぐに実行するときだけの解釈ですか? (シェルスクリプトは通常、この方法で実装されます。)エンジンがファイル全体を取得し、すぐにそれをいくつかのバイトコードにコンパイルして、バイトコードを解釈するときに解釈されますか? (CPythonと同様に、第1ステージのMozillaエンジンはこのように動作します。)エンジンが一度に関数を解析し、JITがそれをネイティブコードにコンパイルするときに解釈されますか?ファイル全体をバイトコードにコンパイルし、必要に応じて一度に1つの関数をJITするエンジンについてはどうですか? (最近のほとんどのスクリプトエンジンはこのように動作し、メインのJava VMはバイトコードへのコンパイルが事前に行われることを除いて、この方法でも動作します。)
コンパイルと解釈の間には多くの色合いがあります。
解釈の最も有用な定義は、「実行時に別個の事前ステップなしで、プログラムのソースコードが実行時に提供される」ことだと思います。この定義では、すべてのJavaScriptエンジンはインタープリターです。しかし、これが確かに解釈の唯一の可能な定義ではありません。
しかし、JavaScriptは解釈のために設計されていますか?ある意味、はい:eval
関数と、実行される文字列としてプログラムコードを指定できるFunction
コンストラクターがあります。実行時にプログラムコードを動的に構築するには、エンジンがソースコードを解釈できる必要があります。しかし、これは他のすべてを前もって作ることができないという意味ではありません。 C++やC#などのコンパイル済み言語でも、ソースコードを取得してメモリ内でコンパイルし、新しいマシンコードにしてから実行できます。そのためのライブラリさえあります:C++のLLVM + ClangとC#のRoslynプロジェクトです。
また、JavaScriptの配信メカニズムはソースコードです。認識されたバイトコード形式はありません。 C#とJavaには公式のバイトコードがあり、誰もがC++がマシンコードとして提供されることを期待しています。しかし、これは言語の本質的な側面ではなく、支配的な使用シナリオです。実際、 Flash内のJavaScriptに近い相対するActionScriptは、実際にはバイトコードとして配信されます(Flashコンパイラはすべてのスクリプトをプリコンパイルします)。
「解釈済み」と「コンパイル済み」の定義について完全に合意されたものはありません。古典的な区別では、コンパイルされた言語はスタンドアロンのバイナリ実行可能ファイルを生成しますが、インタープリター型言語はコードを実行するためにデプロイされたランタイムが必要です。仮想マシン、バイトコードなどは区別を曖昧にします。
しかし、これはおそらく有用な定義です。インタープリタード言語は、標準言語ランタイムがソースコードテキストを入力として受け取り、それを実行できる言語です。その定義により、Perl、Python、Ruby、JavaScript、Shellスクリプトなどが解釈されます(バイトコードやネイティブコードのような中間ステップを使用していても)。 Java、C#、Cなどはそうではありません。また、仕様で正確なWordが使用されていない場合でも、JavaScriptは定義により解釈されます。