JavaScriptのeval()関数とは?使い方・危険性・代替手段を徹底解説
公開日:2026年3月20日 / 対象レベル:初心者〜中級者
この記事でわかること
eval()関数の基本的な仕組みと使い方eval()が役立つ場面・実際のユースケースeval()の重大な危険性とセキュリティリスクJSON.parse()やFunction()コンストラクタなど、他の組み込み関数との比較eval()を使わずに済む安全な代替手段
eval()関数とは何か?基本を押さえよう
eval() は、文字列として渡されたJavaScriptコードを実行時に評価・実行する組み込み関数です。JavaScriptが言語仕様として持っている関数であり、すべてのブラウザ環境やNode.js環境で動作します。
const code = "1 + 2";
const result = eval(code);
console.log(result); // 3
上記の例では、文字列 "1 + 2" が実際のJavaScript式として評価され、数値 3 が返されています。このように、文字列をそのままコードとして動かせるというのが eval() の最大の特徴です。
変数の宣言や関数の定義も可能です。
eval("var x = 10;");
console.log(x); // 10(スコープに注入される)
eval("function greet(name) { return 'Hello, ' + name; }");
console.log(greet("Alice")); // Hello, Alice
eval()が役立つ場面(メリット)
「危険だ」という話が先行しがちな eval() ですが、登場した理由にはそれなりの背景があります。以下のようなユースケースでは、過去に活躍してきました。
1. 動的なコード実行が必要なツール
コードエディタやオンラインのREPL(対話型実行環境)、ブラウザ上で動くJavaScript学習ツールなどでは、ユーザーが入力したコードをその場で実行する必要があります。このような高度に制御された環境では、eval()が使われることがあります。
2. 旧来のJSONパース(歴史的経緯)
JSONが標準化される以前、サーバーからのレスポンスをオブジェクトに変換するために eval() が使われていた時代がありました。
// 昔のコード(現在は絶対にやってはいけない)
const obj = eval("(" + jsonString + ")");
現在は後述する JSON.parse() が正解です。
3. テンプレートエンジンの内部実装
一部のテンプレートエンジンやマクロシステムは、内部的に文字列をコードに変換する処理に eval() や類似の仕組みを使っています。これもライブラリの実装者がリスクを理解したうえで使うという前提があります。
eval()の重大な危険性:なぜ「使うな」と言われるのか
eval() は強力ですが、そのほとんどのユースケースにおいてリスクがメリットを大幅に上回ります。具体的にどのような問題があるのか、一つずつ確認しましょう。
危険性①:XSS(クロスサイトスクリプティング)の温床になる
最も深刻なリスクです。ユーザーが入力したデータをそのまま eval() に渡すと、悪意のあるコードを実行させるXSS攻撃を受ける可能性があります。
// 絶対にやってはいけないコード
const userInput = document.getElementById("input").value;
eval(userInput); // ユーザーが任意のコードを実行できてしまう!
攻撃者が document.cookie を送信するコードや、ページを改ざんするコードを入力すれば、そのまま実行されてしまいます。Webアプリにとってこれは致命的です。
危険性②:デバッグが非常に困難になる
eval() で実行されるコードは、通常のJavaScriptエンジンの最適化パイプラインから外れることが多く、ブラウザの開発者ツールでブレークポイントを張ったり、スタックトレースを正確に確認したりすることが難しくなります。バグが起きたとき、どこで何が起きているのかを追うのが格段に難しくなります。
危険性③:パフォーマンスの低下
JavaScriptエンジン(V8など)は、コードを事前に解析・コンパイルすることで高速な実行を実現しています。しかし eval() で渡される文字列は実行時に初めてパースされるため、JITコンパイルによる最適化が効きにくく、パフォーマンスが著しく低下することがあります。
危険性④:スコープの汚染
eval() はデフォルトで呼び出し元のスコープにアクセスでき、ローカル変数を意図せず上書きしたり、外部から内部の変数を読み取られたりするリスクがあります。
function secret() {
const password = "super_secret_123";
eval(userControlledCode); // passwordが外部から読み取れてしまう可能性
}
危険性⑤:Content Security Policy(CSP)との非互換
現代のWebセキュリティではCSPが広く採用されており、多くの設定で eval() の実行はデフォルトでブロックされます。eval() を使っているコードは、セキュリティを重視した環境ではそもそも動作しないことが増えています。
他の組み込み関数との比較
eval() が「文字列を動的に処理する」文脈で語られることが多いため、似たような目的で使われる組み込み関数と比較してみましょう。
JSON.parse() ── JSONを扱うなら迷わずこちら
| 比較項目 | eval() | JSON.parse() |
|---|---|---|
| 対応フォーマット | 任意のJS式 | JSONのみ |
| セキュリティ | 低(任意コード実行) | 高(データのみ解釈) |
| パフォーマンス | 低 | 高(最適化済み) |
| エラーハンドリング | 例外が起きやすい | SyntaxError を throw |
サーバーからJSONデータを受け取ってオブジェクトにしたいだけなら、JSON.parse() 一択です。eval() を使う理由はありません。
const jsonString = '{"name": "Alice", "age": 30}';
// 悪い例
const obj1 = eval("(" + jsonString + ")");
// 良い例
const obj2 = JSON.parse(jsonString);
Function()コンストラクタ ── evalより少しマシだが油断禁物
new Function(引数, 本体) という書き方で、文字列から関数を生成できます。eval() との違いは、グローバルスコープで実行されるため、呼び出し元のローカル変数にアクセスできない点です。スコープ汚染のリスクは低減されますが、任意コード実行のリスクは残ります。
const add = new Function("a", "b", "return a + b;");
console.log(add(2, 3)); // 5
ローカル変数へのアクセスを遮断できる分、eval() よりは安全ですが、ユーザー入力を直接渡すのは依然として危険です。テンプレートエンジンや設定ファイルから信頼された式を評価するなど、限定的な場面での使用に留めましょう。
setTimeout() / setInterval() の文字列渡し ── 実はeval()と同じ
あまり知られていませんが、setTimeout と setInterval は第一引数に文字列を受け取ることができます。
// これは内部的にeval()と同じ危険性がある
setTimeout("console.log('危険!')", 1000);
// こちらが正しい
setTimeout(() => console.log("安全!"), 1000);
文字列を渡す書き方はeval()と同等の危険性を持ちます。コールバック関数を渡す形を常に使いましょう。
parseInt() / parseFloat() ── 数値変換はこちらで
ユーザー入力を数値として扱いたいとき、eval("42") のような使い方をする例を見かけることがありますが、これは完全にアンチパターンです。
// 悪い例(数値取得にevalは不要、かつ危険)
const num = eval(userInput);
// 良い例
const num = parseInt(userInput, 10);
const float = parseFloat(userInput);
const num2 = Number(userInput);
parseInt() や Number() は数値変換に特化しており、コードを実行する機能を持たないため安全です。
eval()を使わずに済む代替パターン
「動的にコードを動かしたい」という需要のほとんどは、eval() を使わずに解決できます。
パターン①:オブジェクトをディスパッチテーブルとして使う
条件によって異なる処理を呼び出したい場合、eval() で関数名の文字列を実行するのではなく、オブジェクトにマッピングする方法が安全です。
// 悪い例
eval(actionName + "()");
// 良い例
const actions = {
save: () => { /* 保存処理 */ },
delete: () => { /* 削除処理 */ },
export: () => { /* エクスポート処理 */ },
};
if (actions[actionName]) {
actions[actionName]();
}
パターン②:テンプレートリテラルで動的な文字列生成
動的なHTML生成や文字列の組み立てにはテンプレートリテラルが最適です。
const name = "Alice";
const greeting = `こんにちは、${name}さん!`;
パターン③:Web WorkersやSandbox化した iframe
どうしても任意コードを実行させる機能が必要な場合(オンラインコードエディタなど)は、Web WorkersやサンドボックスされたiframeのなかでPostMessageを通じて通信する方式が推奨されます。メインスレームのDOMや変数へのアクセスを物理的に遮断できます。
まとめ:eval()と向き合う正しい姿勢
eval() は確かにJavaScriptの組み込み関数であり、使えないわけではありません。しかし、「できる」と「やるべき」は別の話です。
| 状況 | 推奨アクション |
|---|---|
| JSONを解析したい | JSON.parse() を使う |
| 数値に変換したい | parseInt() / Number() を使う |
| 関数を動的に呼びたい | オブジェクトのディスパッチテーブルを使う |
| 任意コードを実行する機能が必要 | Web WorkerやSandbox iframeを検討する |
| どうしても eval() が必要 | 入力を絶対に信頼しない・CSPを設定する |
MDN Web Docsでも eval() には「eval() を使わないでください(Don't use eval!)」という明確な記述があります。特にユーザーの入力に関わる場面では、eval() を使う選択肢を最初から除外する習慣をつけることが、安全なコードを書くうえで重要です。
初心者のうちは「eval() という便利そうな関数がある」ことを頭の片隅に置きつつ、実際には使わない。それが eval() との最も正しい付き合い方と言えるでしょう。
よくある質問(FAQ)
Q. evalはなぜ最初から存在するの? A. 動的なスクリプト実行やメタプログラミングのニーズに応えるために設計されました。言語が成熟するにつれ、より安全な代替手段が整備され、現在では推奨されない機能となっています。
Q. strictモード('use strict')でevalは安全になる? A. スコープの分離が強化されますが、任意コード実行のリスクは残ります。strictモードはあくまで補助的な対策です。
Q. ライブラリの内部でevalが使われていても問題ない? A. 信頼できるライブラリが内部実装として使っている場合、セキュリティ審査を経ていることがほとんどです。自分のコードでユーザー入力をevalに渡すこととは根本的に異なります。
この記事は定期的に内容を見直し、最新のベストプラクティスに合わせて更新しています。
参考文献
- MDN Web Docs ── eval() https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/eval eval() の公式リファレンス。「eval() を使わないでください」という注記も掲載されている。
- MDN Web Docs ── JSON.parse()https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse JSON文字列をオブジェクトに変換するための標準メソッドの公式解説。
- MDN Web Docs ── Function() コンストラクタhttps://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/Function 文字列から関数を生成する方法と、eval() との違いを確認できる。
- OWASP ── Cross Site Scripting (XSS) https://owasp.org/www-community/attacks/xss/ eval() の誤用が引き起こすXSS攻撃のメカニズムと対策を解説した、セキュリティの世界標準的ガイド。
- ECMAScript 2024 Language Specification ── sec-eval-x https://tc39.es/ecma262/#sec-eval-x eval() の言語仕様上の定義。動作原理を厳密に理解したい場合の一次資料。
- MDN Web Docs ── Content Security Policy (CSP) https://developer.mozilla.org/ja/docs/Web/HTTP/CSP eval() をブロックするCSP設定(
script-srcディレクティブ)の詳細解説。 - Google Developers ── Web Fundamentals: eval() と動的コード評価https://developers.google.com/web/fundamentals/security/csp Googleによるセキュアなウェブ開発ガイドラインの中でのeval()に関する言及。
