eval(“1 2”),->3
ソース コード内の文字列を動的に決定することは非常に強力な言語機能であり、実際に適用する必要はほとんどありません。 eval() を使用する場合は、本当に使用する必要があるかどうかを慎重に検討する必要があります。
1. eval() は関数ですか、それとも演算子ですか
eval() は関数ですが、演算子として扱われます。 。 JavaScript 言語の初期のバージョンでは eval 関数が定義されており、最新の JavaScript インタープリターは広範なコード分析と最適化を実行します。 eval の問題は、一般に動的実行に使用されるコードを分析できないことです。つまり、関数が eval を呼び出した場合、インタープリターは関数をさらに最適化し、eval を関数の別の部分として定義することができません。別の名前 var f=eval を指定できる場合、インタープリタは f() を呼び出す関数を安全に最適化できません。 eval が演算子である場合、これらの問題は回避できます。
2. eval()
eval() にはパラメータが 1 つだけあります。渡されたパラメータが文字列でない場合は、この関数を直接返します。パラメーターが文字列の場合、その文字列は JavaScript コードとしてコンパイルされ、コンパイルが失敗すると構文エラー例外がスローされます。コンパイルが成功した場合、このコード部分が実行され、文字列内の最後の式またはステートメントの値が返されます。最後の式またはステートメントに値がない場合は、最終的に unknown が返されます。文字列が例外をスローした場合、この例外は呼び出しを eval() に渡します。
eval で最も重要なことは、eval が呼び出される変数スコープ環境を使用することです。つまり、変数の値を検索し、ローカル スコープ内のコードとまったく同じように新しい変数と関数を定義します。関数がローカル変数 x を定義して eval("x") を呼び出すと、ローカル変数の値が返されます。 eval("x=1") を呼び出すと、ローカル変数の値が変更されます。関数が eval("var y=2;") を呼び出すと、新しいローカル変数 y が宣言されます。同様に、関数は次のコードを通じてローカル変数を宣言できます。
eval(“関数 f(){return x 1;}”);eval がトップレベルのコードで呼び出された場合、もちろん、グローバル変数とグローバル関数に作用します。
eval に渡される文字列は文法的に一貫している必要があることに注意してください。たとえば、eval("return;") は return のみを再生するため、関数に任意のコード スニペットを貼り付けることはできません。実際、eval 文字列が実行されるときのコンテキストは、関数が呼び出されるコンテキストと同じであるため、関数の一部として実行することはできません。文字列が別個のスクリプトとしてセマンティックである場合、パラメータとして eval に渡すことに問題はありません。そうでない場合、eval は構文エラー例外をスローします。
3. グローバル eval()
eval() にはレイアウト変数を変更する機能がありますが、これは JavaScript オプティマイザーにとって大きな問題です。ただし、応急処置として、JavaScript インタプリタは eval を呼び出す関数に対してあまり最適化を行いません。しかし、スクリプトで eval のエイリアスを定義し、それを別の名前で呼び出す場合、JavaScript インタプリタはどのように動作するのでしょうか? JavaScript インタープリターの実装を簡素化するために、ECMAScript3 標準では、インタープリターが eval にエイリアスを割り当てることを許可されないことが規定されています。 eval 関数がエイリアスを通じて呼び出された場合、EavlError 例外がスローされます。実際には、ほとんどの実装ではこれが行われません。エイリアスを通じて呼び出された場合、eval はその文字列をトップレベルのグローバル コードとして実行します。実行されたコードは、新しいグローバル変数やグローバル関数を定義したり、グローバル変数に値を割り当てたりすることはできますが、呼び出し元の関数でローカル変数を使用したり変更したりすることはできないため、関数内のコードの最適化には影響しません。
ECMAScript5 は EavlError の使用に反対し、eval の動作「直接 eval」を標準化します。eval() 関数が非修飾の「eval」名を使用して直接呼び出される場合、通常は「直接 eval」と呼ばれます。 eval() が直接呼び出される場合、呼び出されたコンテキストのスコープ内で常に実行されます。他の間接呼び出しはグローバル オブジェクトをコンテキスト スコープとして使用するため、ローカル変数や関数の読み取り、書き込み、定義はできません。サンプルコードは次のとおりです:
ECMAScript5 厳密モードでは、eval() 関数の動作、さらには識別子 eval の使用にさらに制限が課されます。 eval が strict モードで呼び出される場合、または eval によって実行されるコード セグメントが "Use strict" ディレクティブで始まる場合、ここでの eval はプライベート コンテキストのローカル eval になります。つまり、厳密モードでは、eval によって実行されるコード セグメントはローカル変数をクエリまたは変更できますが、ローカル スコープで新しい変数や関数を定義することはできません。 さらに、厳密モードでは予約語として「eval」がリストされ、これにより eval() はより演算子に似たものになります。 eval() 関数はエイリアスでオーバーライドできません。そして変数名、関数名。関数パラメータも例外キャプチャ パラメータも eval という名前を付けることはできません。
剣の刃は研ぐことから生まれ、梅の香りは厳しい寒さから生まれます。