eval の機能は実際には非常に単純で、文字列を JS インタープリターに渡し、JavaScript インタープリターがその文字列を Javascript コードに解釈して実行します。
最も単純な例を考えてみましょう。
次のようにコードをコピーします。
<script type="text/javascript">
eval("アラート(1+1)");
スクリプト>
非常に簡単で、文字列をJSコードに解釈して実行すると、2がポップアップ表示されます。
もちろん、上記の例は単なるおもちゃであり、実際に使用するほど愚かな人はいないでしょう。 eval 関数を使用する最も基本的な方法は、DOM 内で行うことだと思います。たとえば、div1、div2、div3 がある場合、document.getElementByID を使用するときに ID を取得する方法はありません。このようなプログラムを結合するには eval を使用します。例えば:
次のようにコードをコピーします。
<script type="text/javascript">
for (var ループ = 1; ループ < 10; ループ++) {
eval('document.getElementById("div"+loop).innerHTML="123"');
}
スクリプト>
最も基本的な使い方を説明した後でも、この機能に興味があるのはこの機能だけだと思います。次に、eval() 関数を少しずつ見てみましょう。
eval のスコープから始めて、この関数を見てみましょう。
次のようにコードをコピーします。
<script type="text/javascript">
eval("var i=3");
アラート(i);
スクリプト>
コードは非常に単純で、結果がポップアップ表示されます。次に、このコードを比較してください。
次のようにコードをコピーします。
<script type="text/javascript">
var テスト = 関数 () {
eval("var i=3");
アラート(i);
}
テスト();
アラート(i);
スクリプト>
結果として、最初に 3 がポップアップし、次に未定義が表示されます。
eval() 関数によって動的に実行されるコードは新しいスコープを作成せず、そのコードは現在のスコープで実行されることを説明します。つまり、 eval() 関数は、現在のスコープ内の this、引数、および他のオブジェクトも使用できます。
IE では、eval() によく似た execScript() という関数がサポートされています。簡単なコードを書くことができます。
次のようにコードをコピーします。
<script type="text/javascript">
var テスト = 関数 () {
execScript("var i=3");
アラート(i);
}
テスト();
アラート(i);
スクリプト>
その結果、3 が 2 つ出てきました。これも execScript 関数の特徴を示しています。まず、文字列を JS コードに解釈して実行できますが、そのスコープは現在のスコープではありません。グローバルスコープ。上記のコードを Firefox と Google Chrome に入れて試してみると、execScript のコードが Firefox では無効であることがわかります。これは、execScript コードのブラウザ互換性にも問題があることを示しています。
そこで問題となるのは、グローバル + ブラウザ互換性という 2 つの機能の「利点」をどのように組み合わせることができるかということです。ネットで調べて自分なりにまとめてみたのですが、おそらくこんな感じです。
次のようにコードをコピーします。
<script type="text/javascript">
var StrongEval = 関数 (コード) {
if (window.navigator.userAgent.indexOf("MSIE") >= 1) {
execScript(コード);
}
if (window.navigator.userAgent.indexOf("Firefox") >= 1) {
window.eval(コード);
}
それ以外 {
execScript(コード);
}
};
var テスト = 関数 () {
StrongEval("var i=3");
}
テスト();
アラート(i);
スクリプト>
これにより、FF と IE との互換性が完全に高まります。重要なコードは、FF では eval と window.eval が同等ではないということです。これは非常に奇妙なことです。
さらに、 eval+with を使用して、いくつかの奇妙なトリックを実現することもできます。
一般的な意味では、次のようなコードを書くことができます。
次のようにコードをコピーします。
var obj = 関数 () {
this.a = 1;
this.b = 2;
this.c = 5;
this.fun = function () {
this.c = this.a + this.b;
}
};
var o = 新しいobj();
o.fun();
アラート(oc);
またはこれ:
次のようにコードをコピーします。
var obj = {
答え: 1、
b:2、
c:5、
楽しい: 関数 () {
this.c = this.a + this.b;
}
}
またはこれ:
次のようにコードをコピーします。
var obj = 関数 () {
this.a = 1;
this.b = 2;
this.c = 5;
};
obj.prototype.fun = function () {
this.c = this.a + this.b;
}
var o = 新しいobj();
o.fun();
アラート(oc);
いくらなんでも、この気持ちには飽きていませんか?次に、少なくとも感覚にとってもう少し快適になるように、まったく異なるアプローチをとってみましょう。
次のようにコードをコピーします。
<script type="text/javascript">
var funtemp = function () {
c = a + b;
}
var obj = {
答え: 1、
b:2、
c:5
};
楽しいです。
with (obj) {
eval("fun = " + funtemp);
}
楽しい();
アラート(obj.c);
スクリプト>
これは非常に強制的でとても良いものですが、それが快適かどうかについては議論しません。そのような状況について話し合いましょう。
次のようにコードをコピーします。
<スクリプト>
varDBCommon = function () {
アラート("1.");
アラート("2.");
アラート("3.");
アラート("4.");
アラート("5.");
}
var SQLServerCommon = {
CreateConnection: function () {alert("SQL Server 接続の確立") };
OpenConnection: function () {alert("SQL Server 接続を開く") };
CreateCommand: function () {alert("SQL Server コマンドの作成");
ExcuteCommand: function () {alert("DSQL サーバー コマンドを実行");
CloseConnection: function () {alert("SQL Server 接続を閉じる");
};
var OracleCommon = {
CreateConnection: function () {alert("Oracle 接続の確立");
OpenConnection: function () {alert("Oracle 接続を開く") };
CreateCommand: function () {alert("Oracle コマンドの作成");
ExcuteCommand: function () {alert("DOracle コマンドを実行");
CloseConnection: function () {alert("Close?Oracle 接続");
};
with (SQLServerCommon) {
eval("forSQLServer=" + DBCommon);
}
with (OracleCommon) {
eval("forOracle=" + DBCommon);
}
forSQLServer();
forOracle();
スクリプト>
これは単純なテンプレート メソッド パターンと考えてよいでしょうか?ふふ。 eval と with を使用してこれを呼び出し、関数のコンテキストを変更することもできます。
しかし、繰り返しになりますが、Eval は一般的な状況ではほとんど使用されないため、使用を完全に避けることができます。