JavaScriptコンパイラ、エンジン、スコープについて話します.

3536 ワード

1言葉から話します
JavaScriptと言えば、みんなの第一反応は脚本言語、解釈性執行などで、java Cのようなコンパイル言語とは相性が悪いです.しかし、実際にはコンパイル言語です.ただ、JSは他のコンパイル言語のように早目にコンパイルされないという違いがあります.彼のコンパイルプロセス(通常)は実際の実行前に行われます.移植可能なコンパイル結果も生まれません.
通常のコンパイルプロセスは、次のいくつかのステップを行います.まず、単語と語法の分析を行い、入力した文字列をプログラミング言語に意味のあるコードブロックに分解します.第二のステップの解析と文法分析は、このステップの操作が多く、前のステップの語彙ユニットの集合を分析して、最終的に要素の階層的な入れ子からなるプログラム文法構造を表すツリーに変換します.これは (Abstract Syntx Tree、AST)といいます.第3ステップコード生成とは、前のステップのASTを実行可能コードに変換することである.JavaScriptエンジンのコンパイラがすることはこれと似ていますが、JSエンジンのコンパイルプロセスはコード実行前のものですので、「ユーザー」にとっては完全に透明です.また、事前にコンパイルを実行して静的ファイルを生成することができませんでしたので、JSのコンパイルの実行効率は一般的な静的言語よりも敏感なので、非常に複雑です.JSエンジンはこの部分で非常に多くの最適化を行いました.一つは文法分析とコード生成段階の最適化(例えば冗長要素の最適化など)に対して、コンパイル後の実行効率を高めることを目的としています.二つ目は、コンパイルプロセスの最適化(JIT、遅延コンパイル、または再コンパイル)に対して、最適な性能を保証するためにコンパイルプロセスを短縮することを目的としています.
2この三兄弟について話してください.
  • エンジン:JSプログラム全体のコンパイルと実行プロセス
  • を担当します.
  • コンパイラ:文法分析やコード生成などの仕事を担当しています.
  • 作用領域:全声明の識別子(変数)からなる一連のクエリを収集して維持し、非常に厳格なルールを実施し、現在実行されているコードがこれらの識別子に対するアクセス権限を決定する
  • .
    はっきり言って、スコープは何ですか?は変数の「管理者」で、事前に定義されたルール(語法のスコープ)を使って、変数の検索とアクセスを管理します.
    三兄弟協力:第一版
    以下、最も簡単な例var a = 2で分析します.
  • コンパイラが登場し、まず品詞分析を行い、その割当値を分割します.var a;a=2;.第1ステップvar aでは、コンパイラが処理できます.彼は先に変数管理者に聞きます.スコープにはこの名前の変数がありますか?もし存在するならば、引き続きコンパイルします.存在しない場合、スコープに新しい変数を宣言します.名前はaです.
  • コンパイラは、主にa=2のこの割当動作を処理するためにエンジンのコード生成を継続する.
  • エンジンは実行可能なコードを取得して、作用領域に聞きます.今はaという変数がありますか?もしあるならば:この変数を使って、彼に値を与えます.もしないならば、引き続き上級の作用の域に探して、もしルートの作用の域までやはり探し出せないならば、エンジンは直接間違いを報告して異常を投げて、老子はしないで、私を遊びます.
    ここに変数検索に関する概念を紹介します.
  • LHS:値付け動作の左側で、変数の容器そのものを検索しようとして、値付けができます.すなわちコピー動作のターゲットが見つかります.
  • RHS:別のルックアップは、コピー動作の右側として単純に理解され、そのルックアップターゲットは、ターゲットのソース値を取得すること、すなわち、コンテナではなくこの変数の特定の値を見つけることである.
  • 例を挙げます
    var a;//LHS   a,   ,            ,   a
    a=2;//LHS   a     2
    console.log(a);//RHS  a  2,     
    
    三兄弟協力:第二版
    上の基礎知識がありました.三兄弟の協力をもう少し詳しくして、例もアップグレードして、上で値をつけて出力した例です.
  • コンパイラ:スコープ、私はaをLHSで検索する必要がありますが、見たことがありますか?
  • 作用域:これは全然見てないですよ.じゃ、一つ声明しましょう.
  • コンパイラ:はい、できました.コードを生成しました.エンジンは必要なコードをあげます.
  • エンジン:はい、aが必要です.スコープはLHSを探してもらえますか?
  • 作用領域:見つかりました.コンパイラが声明を出してくれました.
  • エンジン:はい、それには価値があります.
  • エンジン:スコープ、意味がないです.私はコンサートに会います.RHS参照
  • が必要です.
  • 作用域:見つけました.内蔵対象です.持って行ってもいいです.
  • エンジン:はい、作用域です.aのRHSを確認してもらえますか?
  • 作用域:確認しました.変えていません.持って行って使ってください.彼の値は2
  • です.
  • エンジン:はい、ロゴ(.)
  • に伝えます.
    疑問:どうしてこんなにくどい区別が必要ですか?LHSとRHS?実際に注意すれば、あなたはすでに発見したはずです.この二つの検索には重要な違いがあります.すなわち変数が見つからない時の行動が違います.
  • RHSが見つかりませんでした.エンジンがエラーを投げます.Refrence Errer
  • LHSが見つかりませんでした.エンジン(またはエンジン中のコンパイラ)はトップレベルのスコープでこの名前を持つ変数を宣言します.(厳格モードを除く)
  • ここまで言うよりも、この三兄弟の協力についてよく知っていますよね?ほほえみ顔:-D
    3 one more thing…
  • 品詞作用領域:作用域を紹介する時、変数の検索と引用を管理する規則に基づいて、語法作用域はjsの使用規則であり、コンパイラが品法化する時、コードを書く時に変数とブロックの作用領域をどこに書くかによって規則の内容を決定すると述べました.この中にはまた、ブロックスコープという概念が含まれています.展開しない限り、ES 6を覚えておく前にブロックスコープがない限り、関数だけが作用します.すなわち、関数の内部は独立したブロックスコープです.(特殊な例があります.catch文ブロック内も独立した作用領域です.)
  • 変数のアップグレード:コンパイラとエンジンの間の分業が分かりました.変数のアップグレードはそんなに怪しいとは思いません.エンジンがコードを取得した時、コンパイラはもういくつかの転換をしました.コンパイラはなぜこの仕事をしますか?彼が第一歩ですべての声明を見つけて、適切なスコープで彼らを結びつけるために、これはまさにフレーズのスコープの核心です.変数と関数を含むすべての声明は、現在のブロックのスコープ内で最初に処理されます.すなわち、前のステートメントにアップグレードされたようなものですが、コピー処理は実行段階なので、コンパイル段階では元の場所で実行を待っています.練習を二つ残してもいいですか?
  • //       《       》     
    //     :
    a=2
    var a;
    console.log(a);
    
    //     :
    console.log(a);
    var a = 2;
    
    理解が浅いです.誤謬が多いかもしれません.コメント検討を歓迎します.-)
    原文のリンク:http://www.jianshu.com/p/36f5bfc6b7e6 chagchaoの転載は出所を明記してください.