eval()
文字列として指定されたコードをJavaScriptのコードとして評価します。
文法
eval(string)
引数 | 説明 |
---|---|
string | JavaScriptの式、記述などのコードを文字列で指定します。 この式には、値と既存のオブジェクトのプロパティを含めることが可能です。 |
説明
eval()はグローバルオブジェクトの関数プロパティです。
eval()関数の引数は、文字列になります。 もし、文字列が式であれば、eval()はその式を評価します。 引数が1つまたは複数のJavaScriptの記述を表すのであれば、 eval()はその文を評価します。 JavaScriptは計算式を自動的に評価します。
もし、文字列として計算式を組み立てた場合、 eval()を使用して後ほどそれを評価することが可能です。 例えば、変数xがあるとします。 "3 * x + 2"とする式を文字列値として変数へ割り当て、スクリプト内の後ろの地点でeval()を呼び出すことで、 xを伴う式の評価を延期することが可能です。
もし、eval()の引数が文字列で無ければ、eval()は引数をそのまま返します。 下記の例では、Stringコンストラクタを明示的に指定しており、 eval()は文字列を評価した結果では無く、Stringオブジェクトを返しています。
eval(new String("2 + 2")); // "2+2"を含むStringオブジェクトを返す
eval("2 + 2"); // 4を返す
一般的な方法としてtoString()
を使用することで、この制限を回避することが可能です。
var expression = new String("2 + 2");
eval(expression.toString());
eval()を別の名前を介して、間接的に使用することは出来ません。 これを行うと、ランタイムエラーが発生するかもしれません。 例えば、下記のようなコードを使用するべきではありません。
var x = 2;
var y = 4;
var myEval = eval;
myEval("x + y");
evalは出来るだけ使用しないで下さい!
eval()は、呼び出し元の権限で渡したコードを実行することの出来る危険な関数です。 もし、悪意のある第三者による影響を受ける可能性がある文字列がeval()で実行された場合、 Webページ(またはエクステンション)の権限で、悪意のあるコードがユーザーのマシン上で実行されてしまう恐れがあります。 更に重要なことに、サードパーティ製のコードがeval()が実行されるスコープ上を参照することが出来る状態であると、 影響されにくいはずの同様の関数にまで、攻撃が及ぶ可能性があります。(翻訳に自信なし)
また一般的に、eval()はモダンJavaScriptエンジンによるJSインタプリタよりも実行速度が遅くなります。
eval()に代わる、より安全(且つより高速)な一般的な方法が存在します。
メンバプロパティへのアクセス
プロパティ名を実際のプロパティに変換することに、eval()を使用すべきではありません。 コードが実行されるまで、アクセスされるオブジェクトのプロパティを知ることが出来ない、下記の例で考えてみましょう。 これは、evalを使用して実行することが可能です。
var obj = { a: 20, b: 30 };
var propname = getPropName(); //"a"または"b"が返るとします
eval( "var result = obj." + propname );
ただし、ここでeval()は必要ありません。
更に言えば、このような使用はお勧め出来ません。
代わりにより高速で安全なメンバ演算子(訳注: obj[propname]
のような)を使用してください。
var obj = { a: 20, b: 30 };
var propname = getPropName(); //"a"または"b"が返るとします
var result = obj[ propname ]; //obj["a"]は、obj.aと同等です。
コードの断片の評価に関数を使用
Javascriptは第一級関数を持ち、 これは他のAPIに対して引数として関数を渡し、それらを変数に格納したり、オブジェクトのプロパティにするといった事が可能であることを意味します。 多くのDOM APIはこの考えに基いて設計されており、 次のように書くことが可能です。(また、書くべきです。)
// setTimeout(" ... ", 1000)と書く代わりに
setTimeout(function() { ... }, 1000);
// elt.setAttribute("onclick", "...")と書く代わりに
elt.addEventListener("click", function() { ... } , false);
また、クロージャも、文字列の連結をすること無く、 パラメータ化された関数を作成する方法として有用です。
JSONの解析(文字列をJavaScriptオブジェクトへ変換)
コードでは無く、データを含む文字列(例えば、配列"[1, 2, 3]")をeval()呼び出しする場合、 文字列をデータを表すJavaScript文法のサブセットとして使用する事が出来る、JSONに変更することを検討すべきです。
JSON文法はJavaScript文法と比べて制限があるため、多くの正式なJavaScriptリテラルがJSONとして解析されないことに注意してください。 例えば末尾のカンマ(trailing commas)は、JSONでは許可されておらず、 オブジェクトのリテラルのプロパティ名(キー)はクォートで囲まなければいけません。 後ほどJSONとして解析される文字列を生成するJSONシリアライザーを、使用する前に確認するようにしてください。
コードの代わりにデータを渡す
例えば、WEBページのコンテンツをスクレイピングするために設計されたエクステンションは、 JavaScriptコードの代わりにXPathを定義したスクレイピングのルールを持ちます。
制限された権限によるコードの実行
もし、どうしてもexec()を使用してコードを実行しなければならない場合は、 権限を出来るだけ減らして実行することを検討してください。 これは主にエクステンションとXULアプリケーションに対してのアドバイスであり、 このためにComponents.utils.evalInSandboxが用意されています。
例
下記の例は、document.writeを使用して出力を表示します。
サーバーサイド側のJavaScriptであれば、document.write()を使用する代わりに、
write()
を使用して同じように出力を表示することが可能です。
下記のeval()
を含むどちらのコードも、42を返します。
1つ目は"x + y + 1";
の文字列が評価され、
2つ目は"42"
の文字列が評価されます。
var x = 2;
var y = 39;
var z = "42";
eval("x + y + 1"); // returns 42
eval(z); // returns 42
例: evalを使用してJavaScirpt記述の文字列を評価
下記の例は、eval()
を使用してstr
文字列を評価しています。
このJavaScriptの記述で構成された文字列は、アラートダイアログを開き、x
が5であれば42の値を割り当て、
そうでなければz
へ0を割り当てます。
2行目の文が実行されると、eval()はこれらの記述を実行し、
設定されている値を評価し、z
に割り当てられる値を返します。
var x = 5;
var str = "if (x == 5) {alert('z is 42'); z = 42;} else z = 0; ";
document.write("<P>z is ", eval(str));
例: 最後の式が評価される
eval()
は最後の式で評価された値を返します。
var str = "if ( a ) { 1+1; } else { 1+2; }";
var a = true;
var b = eval(str); // returns 2
alert("b is : " + b);
a = false;
b = eval(str); // returns 3
alert("b is : " + b);
仕様
ブラウザ互換性
機能 | Chrome | Firefox (Gecko) |
IE | Opera | Safari |
---|---|---|---|---|---|
基本 | ◯ | ◯ | ◯ | ◯ | ◯ |
機能 | Android | Chrome for Android |
Firefox Mobile |
IE Mobile |
Opera Mobile |
Safari Mobile |
---|---|---|---|---|---|---|
基本 | ◯ | ◯ | ◯ | ◯ | ◯ | ◯ |
関連項目
© 2017 Mozilla Contributors
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
このページは、ページトップのURL先のMozilla Developer Network(以下、MDN)のコンテンツを翻訳した内容を基に構成されています。 構成について異なる点も含まれますので、下記の項目を確認し、必要に応じて元のコンテンツをご確認ください。 もし、誤訳などの間違いを見つけましたら、 @tomofまで教えていただければ幸いです。
- 特定のブラウザに特化しすぎている情報やあまりにも古い情報、 または試験的に導入されているようなAPIや機能については、省略していることがあります。
- 例やデモについて、実際にページ内で動作させる関係で一部ソースコードを変更している場合や、 その例で使用しているコンテンツの単語や文章などを日本人向けに変更しいてる場合があります。
- MDNの更新頻度が高いため、元のコンテンツと比べ情報が古くなっている可能性があります。
- "訳注:"などの断わりを入れた上で、日本人向けの情報の追記を行っている事があります。