JavaScriptは設計によって解釈されますか?


73

私はこの質問をするのは用心深いです。JavaScript:The Definitive Guideを開いたところ、第1章の最初のページの状態

「JavaScriptは、高レベルで動的な、型付けされていないインタープリタ型プログラミング言語です」

だから、解釈された部分は言語仕様の要件であると解釈するのですか、それとも言語とその多くの実装の違いを尊重するときに言語が解釈されるプログラミング言語であると言うのは誤解を招くのでしょうか?

JavaScriptのための静的コンパイラは明らかにありません- https://stackoverflow.com/questions/1118138/is-there-a-native-machine-code-compiler-for-javascriptので、多分それは、このだけの反射です。


しばらくの間、AS3 /「失われた」ES4に似たjscript.netがありました。CILにバイトコードでコンパイルされました。
ヘイ

13
V8は、インタプリタではなくコンパイラであることを明示的に主張しています。
pimvdb

@GGG JScript.Netはまだ生きています... しかし、まだ生きています。msdn.microsoft.com/en-us/library/72bd815a.aspx
ジェッティ

1
FWIWは、「型なし」ビットは、いずれかの厳密には正しくない
ロブ・寒天

FirefoxはFF 3.5で質問に答えた年に最初のブラウザベースのJITコンパイラをリリースしたばかりであり、おそらく当時はあまり知られていなかったでしょう。現代のJITは、実際にはJSドキュメントの最初のパスで多くのコンパイル(または少なくともコンパイルの準備)を行い、特定のスコープに分離されたメソッドの識別やキャッシュなどを行います。
エリックReppen

回答:


50

だから、解釈された部分は言語仕様の要件であると解釈するのですか、それとも言語とその多くの実装の違いを尊重するときに言語が解釈されるプログラミング言語であると言うのは誤解を招くのでしょうか?

EcmaScript言語のオタクは、「ESインタープリター」という用語を使用してEcmaScriptの実装を指すことがよくありますが、仕様ではその用語を使用していません。言語の概要、特にはインタプリタに依存しないという点で言語について説明します。

ECMAScriptはオブジェクトベースです。基本言語とホスト機能はオブジェクトによって提供され、ECMAScriptプログラムは通信するオブジェクトのクラスターです。

そのため、EcmaScriptは、オブジェクト定義のプロバイダーとして定義される「ホスト環境」を想定します。これは、I / Oまたは外部へのリンクを許可するすべてのものを含むが、インタープリターを必要としません。

言語のステートメントおよび式のセマンティクスは、インタープリターで簡単に実装される補完仕様の観点から定義されていますが、仕様ではそれを必要としません。

8.9完了仕様タイプ

完了型は、文(の動作を説明するために使用されbreakcontinuereturnおよびthrowコントロールの非ローカル転送を行います)。Completionタイプの値は、フォーム(typevaluetarget)のトリプルです。ここで、typenormalbreakcontinuereturn、またはthrowのいずれか、valueはECMAScript言語値またはemptytargetはECMAScript識別子またはです。

「突然の完了」という用語は、normal以外のタイプの完了を指します。

制御の非ローカル転送は、ネイティブまたはバイトコードのコンパイルを可能にするジャンプを使用して、命令の配列に変換できます。

「EcmaScriptエンジン」は、同じアイデアを表現するより良い方法かもしれません。


明らかにJavaScript用の静的コンパイラはありません

本当じゃない。V8「インタープリター」は内部でネイティブコードにコンパイルされ、Rhinoはオプションで内部的にJavaバイトコードにコンパイルされ、さまざまなMozillaインタープリター({Trace、Spider、Jager} Monkey)はJITコンパイラーを使用します。

V8

V8は、バイトコードを実行または解釈するのではなく、JavaScriptを実行する前にネイティブマシンコードにコンパイルすることでパフォーマンスを向上させます。

Rhino

public final void setOptimizationLevel(int optimizationLevel)

現在の最適化レベルを設定します。最適化レベルは-1〜9の整数であることが期待されます。負の値は-1として解釈され、9より大きい値は9として解釈されます。最適化レベル-1は、解釈モードが常に中古。レベル0〜9は、クラスファイルが生成される可能性があることを示します。最適化レベルを高くすると、コンパイル時のパフォーマンスと実行時のパフォーマンスがトレードオフになります。実行時にオプティマイザーパッケージが存在しない場合、オプティマイザーレベルを-1より大きく設定することはできません。

TraceMonkey

TraceMonkeyは、ネイティブコードのコンパイルをMozillaのJavaScript®エンジン(「SpiderMonkey」として知られる)に追加します。UC Irvineで開発された「トレースツリー」と呼ばれる手法に基づいており、Tamarin Tracingプロジェクトと共有されるコードとアイデアに基づいています。最終的な結果として、ブラウザーのクロムとWebページのコンテンツの両方の速度が大幅に向上します。


1
この答えをありがとう、それは実際に質問に答えます。静的なコンパイルがないという最終コメントは、どの実装が実際にコードをコンパイルし、どの実装がコンパイルしないかについての話題を引き起こしたものだと思います。私が興味を持ったのは、実装の引用と仕様による定義の欠如を考慮すると、「JavaScriptはインタープリター言語です」というステートメントの妥当性だけで、誤っているように見えました。「決定版ガイド」の2番目の段落を奨励していないが、私はそれに固執すると思います。
マットエッシュ

@ me232、この声明は2008年以前は実質的に真実でした。Rhinoは以前はそれが主要な通訳ではなかったため、それを無視して「決定版ガイド」に違反した人はほとんどいませんでした。私は本を​​読んでいないので、その文が全体的な品質をどの程度代表しているかについてコメントすることはできません。
マイクサミュエル

「静的コンパイラ」の定義は何ですか。定義とは、コンパイルが1回だけ行われ、静的(つまり、不変)のビットバケットを取得してから実行することを意味すると考えました。私の知る限り、これはJavaScriptエンジンの動作方法ではありません。それが彼らがde-optimizationステップを持っている理由です。つまり、JavaScriptはこれらのエンジンによってコンパイルされますが、静的にはコンパイルされません。
-gman

@ gman、Rhinoのバイトコードジェネレーターはそのように動作します。
マイクサミュエル

私の知る限りではありません。Rhinoには、実行時にコンパイルする必要がある他のJavaScriptファイルを含めることができます。それは静的な合併症ではありません。
gman

20

Chromeで使用されるV8 JavaScript VMにはインタープリターが含まれていません。代わりに、2つのコンパイラで構成され、オンザフライでコードをコンパイルします。コンパイラーの1つは迅速に実行されますが、非効率的なコードを生成し、もう1つは最適化コンパイラーです。

V8はコードが実行されるたびにソースコードを入力として受け取り、ユーザーはV8をインストールする必要があるため、一部の人々がこの「不正行為」を考慮する理由を理解できます。しかし、完全なインタープリターとバイトコードを含む実行可能ファイルを出力するコンパイラーを検討してください。次に、スタンドアロンプ​​ログラムを作成します。あまり効率的ではありません。


19

スクリプト言語用のJITコンパイラーの登場により、コンパイルと解釈の境界があいまいになり、質問がそれほど意味をなさないようになりました。エンジンがコードの行を読み取り、すぐに実行するときにのみ解釈されますか?(シェルスクリプトは、通常、このように実装されます。)エンジンがファイル全体を取得し、すぐにそれをバイトコードにコンパイルしてから、バイトコードを解釈するときは解釈しますか?(最初の段階のMozillaエンジンは、CPythonと同様にこのように動作します。)エンジンが一度に関数を解析し、それをネイティブコードにJITコンパイルするとき、それは解釈されますか?ファイル全体をバイトコードにコンパイルし、必要に応じて一度に1つの関数をJITするエンジンについてはどうでしょうか。(最近のほとんどのスクリプトエンジンはこのように機能しますが、

コンパイルと解釈の間には多くの色合いがあります。

解釈のための最も有用な定義は、「実行時にプログラムのソースコードが供給され、独立した事前のステップなし」であると思います。この定義により、すべてのJavaScriptエンジンはインタープリターです。しかし、これは確かに解釈の唯一の可能な定義ではありません。

しかし、JavaScriptは解釈用に設計されていますか?ある意味では、そうです。それは、実行される文字列としてプログラムコードを与えることができるeval関数とFunctionコンストラクタを持っています。実行時にプログラムコードを動的に構築するには、エンジンがソースコードを解釈できる必要があります。しかし、これはあなたが事前に他のすべてを作ることができないという意味ではありません。C ++やC#などのコンパイル済み言語でも、ソースコードを取得し、メモリ内で新しいマシンコードにコンパイルして実行できます。そのためのライブラリもあります:C ++のLLVM + ClangおよびC#のRoslynプロジェクト。

また、JavaScriptの配信メカニズムはソースコードです。認識されるバイトコード形式はありません。C#とJavaには公式のバイトコードがあり、誰もがC ++がマシンコードとして配信されることを期待しています。しかし、これは言語の固有の側面ではなく、単なる支配的な使用シナリオです。実際、FlashのJavaScriptの近い相対ActionScriptは、実際にはバイトコードとして配信されます(Flashコンパイラはすべてのスクリプトをプリコンパイルします)。


4

「解釈された」対「コンパイルされた」の定義について完全に合意されたものはありません。従来の区別では、コンパイルされた言語はスタンドアロンのバイナリ実行可能ファイルを生成しますが、インタープリター言語はコードを実行するためにデプロイされたランタイムを必要とします。仮想マシン、バイトコードなどは区別を曖昧にします。

しかし、ここにおそらく有用な定義があります。インタープリター言語とは、標準言語ランタイムが入力としてソースコードテキストを取得して実行できる言語です。その定義により、Perl、Python、Ruby、JavaScript、シェルスクリプトなどが解釈されます(バイトコードやネイティブコードなどの中間ステップを使用する場合でも)。Java、C#、Cなどはそうではありません。また、仕様で正確な単語が使用されていない場合でも、JavaScriptは定義により解釈されます。


うーん、JavaとCを同じカテゴリーに入れるのは好きではありません。おそらくより良い区別は、(A)ソースコード、(B)中間コード、または(C)マシンコードとして最も一般的に配布される言語です。たとえば、A = javascript、B = Java、C = C。
ジョンヘンケル

解釈またはコンパイルされた言語の呼び出しは正しくありません。たとえば、そのルールの下では、C ++がコンパイルされた言語であることに同意しますか?それでは、Clingコードをコンパイルせずに実行します。「バイトコードやネイティブコードなどの中間ステップを使用する場合でも)などが解釈されます。これに応じて、Javaも解釈され、VMによって解釈されます。
Abhinav Gauniyal
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.