JavaScript でグローバル関数 eval() を使用する方法の詳細なコード例

伊谢尔伦
リリース: 2017-07-25 11:37:40
オリジナル
1458 人が閲覧しました

ソースコード内の文字列の動的決定は非常に強力な言語機能であり、実際に適用する必要はほとんどありません。 eval() を使用する場合は、本当に使用する必要があるかどうかを慎重に検討する必要があります。

1. eval() は関数ですか、それとも演算子ですか?

eval() は関数ですが、演算子として扱われているためです。 。 JavaScript 言語の初期のバージョンでは eval 関数が定義されており、最新の JavaScript インタープリターは広範なコード分析と最適化を実行します。 eval の問題は、一般に動的実行に使用されるコードを分析できないことです。つまり、関数が eval を呼び出した場合、インタープリターは関数をさらに最適化し、eval を関数の別の部分として定義することができません。別の名前 var f=eval を指定できる場合、インタープリタは f() を呼び出す関数を安全に最適化できません。 eval が演算子である場合、これらの問題は回避できます。

2. eval()

eval() にはパラメータが 1 つだけあります。渡されたパラメータが文字列でない場合は、この関数を直接返します。パラメーターが文字列の場合、その文字列は JavaScript コードとしてコンパイルされ、コンパイルが失敗すると構文エラー例外がスローされます。コンパイルが成功した場合、このコード部分が実行され、文字列内の最後の式またはステートメントの値が返されます。最後の式またはステートメントに値がない場合は、最終的に unknown が返されます。文字列が例外をスローした場合、この例外は呼び出しを eval() に渡します。

eval について最も重要なことは、それが呼び出される変数スコープ環境を使用することです。つまり、変数の値を検索し、ローカル スコープ内のコードとまったく同じように新しい変数と関数を定義します。関数がローカル変数 x を定義して eval("x") を呼び出すと、ローカル変数の値が返されます。 eval("x=1") を呼び出すと、ローカル変数の値が変更されます。関数が eval("var y=2;") を呼び出す場合、新しいローカル変数 y を宣言します。同様に、関数は次のコードを通じてローカル変数を宣言できます:

eval("function 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 はその文字列をトップレベルのグローバル コードとして実行します。実行されたコードは、新しいグローバル変数やグローバル関数を定義したり、グローバル変数に値を割り当てたりすることはできますが、呼び出し元の関数でローカル変数を使用したり変更したりすることはできないため、関数内のコードの最適化には影響しません。

ECMAScript 5 は EavlError の使用に反対し、eval の動作である「直接 eval」を標準化します。これは通常、修飾されていない「eval」名を使用して eval() 関数が直接呼び出される場合に「直接 eval」と呼ばれます。 eval() が直接呼び出される場合、それが呼び出されたコンテキストのスコープ内で常に実行されます。他の間接呼び出しは、グローバル オブジェクトをコンテキスト スコープとして使用するため、ローカル変数や関数の読み取り、書き込み、定義はできません。サンプルコードは次のとおりです:

var geval=eval;                //使用别名调用evla将是全局eval
var x="global",y="global";    //两个全局变量
function f(){                //函数内执行的是局部eval
    var x="local";            //定义局部变量
    eval("x += ' chenged';");//直接使用eval改变的局部变量的值
    return x;                //返回更改后的局部变量
}
Function g(){                //这个函数内执行了全局eval
    var y="local";
    geval("y += ' changed';"); //直接调用改变了全局变量的值
    return y;
}
console.log(f(),x);            //改变了布局变了,输出 “local changed global”
console.log(g(),y);            //改变了全局变量,输出    “local global changed”
ログイン後にコピー

グローバル評価のこれらの動作は、コードを最適化する必要性のために作られた単なる妥協ではなく、実際にはそれらを実行できるようにする非常に便利な機能です。コンテキストは、グローバルスクリプトセクション。コードセグメントを実行するために eval が実際に必要となるシナリオはほとんどありません。しかし、その必要性を本当に理解すると、ローカル eval の代わりにグローバル eval を使用する可能性が高くなります。

4. 厳密な eval()

ECMAScript5 厳密モードでは、eval() 関数の動作、さらには識別子 eval の使用にさらに制限が課されます。 eval が strict モードで呼び出される場合、または eval によって実行されるコード セグメントが "Use strict" ディレクティブで始まる場合、ここでの eval はプライベート コンテキストのローカル eval になります。つまり、厳密モードでは、eval によって実行されるコード セグメントはローカル変数をクエリまたは変更できますが、ローカル スコープで新しい変数や関数を定義することはできません。

さらに、strict モードでは予約語として「eval」がリストされ、これにより eval() はより演算子に似たものになります。 eval() 関数はエイリアスでオーバーライドできません。そして変数名、関数名。関数パラメータも例外キャプチャ パラメータも eval という名前を付けることはできません。

以上がJavaScript でグローバル関数 eval() を使用する方法の詳細なコード例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート