6

JavaScriptはエイリアシングevalを許可しますか? 次のコードの最初の部分は予期しない動作をしますが (1、1 を表示)、2 番目の部分はそうではありません (1、2 を表示)。ECMA スクリプトまたは mozilla ドキュメントへの参照が役立ちますが、見つかりませんでした。

<html>
<script type="application/javascript;version=1.8">
    (function(){
        eval('var testVar=1');
        alert(testVar);
        var eval2=eval;
        eval2('var testVar=2');
        alert(testVar);
    })();

    (function(){
        eval('var testVar=1');
        alert(testVar);
        eval('var testVar=2');
        alert(testVar);
    })();
</script>
</html>
4

2 に答える 2

7

「エイリアス」evalを使用して、同じように動作することを期待することはできません。そのような単純な。なんで?eval関数ではありません。

何が起こっているかというと、 を呼び出すときにeval2、変数「キャッシュ」を設定してグローバル変数を操作するということです。したがって、その中に変数を設定することで、グローバル変数を設定しています。ただし、終了すると、変数「キャッシュ」は関数スコープのものに戻ります。2 番目alertが 1 を示しているのはそのためです。グローバル変数は関数レベル 1 によって隠されています。

これは、ECMAScript (強調鉱山) の付録 E (239 ページ) に記載されています。

10.4.2: 第 5 版では、eval 関数への間接呼び出しは、eval コードの変数環境とレキシカル環境の両方としてグローバル環境を使用します。Edition 3 では、間接 eval の呼び出し元の変数および字句環境が、eval コードの環境として使用されました。

「評価コードの入力」に関する完全な定義は、§10.5.2 (page 58) で定義されています (強調は私のものです)。

  1. 呼び出しコンテキストがない場合、またはeval 関数への直接呼び出し (15.1.2.1.1) によって eval コードが評価されていない場合、
    • 10.4.1.1 で説明されているように、eval コードを C として使用して、グローバル実行コンテキストであるかのように実行コンテキストを初期化します。
  2. そうしないと、
    • ThisBinding を、呼び出し元の実行コンテキストの ThisBinding と同じ値に設定します。
    • LexicalEnvironment を呼び出し実行コンテキストの LexicalEnvironment と同じ値に設定します。
    • VariableEnvironment を呼び出し実行コンテキストの VariableEnvironment と同じ値に設定します。
  3. eval コードが厳密なコードの場合、
    • 引数として LexicalEnvironment を渡して NewDeclarativeEnvironment を呼び出した結果が strictVarEnv であるとします。
    • LexicalEnvironment を strictVarEnv に設定します。
    • VariableEnvironment を strictVarEnv に設定します。
  4. eval コードを使用して、10.5 で説明されているように宣言バインディングのインスタンス化を実行します。
于 2013-07-21T09:21:13.247 に答える
2

を使用する最初のケースevalでは、実行される関数スコープが使用されます。同じステートメントを割り当てevalて実行すると、関数コンテキストではなくコンテキスト(グローバルスコープ)を使用しているようです。関数の内側が 1 で外側が 2 であるため、最初のケースで同じ値 1 が表示されるのはそのためです。これは、以下のスニペットを実行することで証明できます。eval2windowtestVarwindow.testVar

<script>
(function(){
        eval('var testVar=1');
        alert(window.testVar);
        var eval2=eval;

        eval2('var testVar=2');
        alert(window.testVar);
    })();

    (function(){
        eval('var testVar=1');
        alert(testVar);
        eval('var testVar=2');
        alert(testVar);
    })();
</script>

実際には、Mozilla Developer Networkによると、eval を別名にすることはできません。

于 2013-07-21T09:28:04.300 に答える