では、先ほど話した「クロージャと eval の危険性」を理解するための
複雑だけど学びの多い練習サンプル4本セット を順番にすべて紹介します。
それぞれに
- 💡 学びのポイント
- 🧠 コード例
- 🔍 結果・解説
をセットで掲載しています。
(すべてブラウザのコンソールやNode.jsでそのまま動作します)
サンプル①:安全なクロージャの例
💡 学び
関数が「外の変数」を覚えていることで、外部から直接アクセスできない値を保持できる。
🧠 コード
function createSecretHolder(secret) {
return {
getSecret: function() {
return secret;
},
setSecret: function(newSecret) {
secret = newSecret;
}
};
}
const holder = createSecretHolder("🍎りんごの暗号");
console.log(holder.getSecret()); // 🍎りんごの暗号
holder.setSecret("🍇ぶどうの暗号");
console.log(holder.getSecret()); // 🍇ぶどうの暗号
// 外から直接アクセスはできない
console.log(holder.secret); // undefined
JavaScript🔍 結果と解説
secretは関数スコープの中だけで保持されており、外部から直接改ざんできません。- これが「クロージャでプライベート変数を作る」典型例です。
サンプル②:toString() + eval の危険な例(スコープ喪失)
💡 学び
toString() した関数を eval で再生成すると、外部変数とのつながりが消える。
🧠 コード
function makeAdder(x) {
return function(y) {
return x + y;
};
}
const add10 = makeAdder(10);
console.log(add10(5)); // 15
// 関数を文字列化
const str = add10.toString();
console.log("文字列化結果:", str);
// evalで復元
const broken = eval('(' + str + ')');
console.log(broken(5)); // ❌ ReferenceError: x is not defined
JavaScript🔍 結果と解説
xはmakeAdder()の中でしか存在しません。- 文字列化して再生成した関数にはその「外側の記憶」がないため、
xが未定義になりエラー。 - ✅ クロージャの仕組みは文字列には含まれない!
サンプル③:悪意ある eval(危険な使い方)
💡 学び
eval() は 実行時に任意のコードを動かすため、ユーザー入力に使うのは非常に危険。
🧠 コード
function runUserCode(code) {
try {
console.log("実行します:", code);
eval(code);
} catch (e) {
console.error("エラー:", e.message);
}
}
// 安全そうに見える入力
runUserCode("console.log('こんにちは');");
// 悪意ある入力
runUserCode("alert('ハッキング!');");
runUserCode("document.body.innerHTML = '<h1>乗っ取られた!</h1>';");
JavaScript🔍 結果と解説
eval()は、そのままコードを実行してしまうため、
ユーザーが送った文字列に悪意ある内容があれば、すぐに被害が発生します。- セキュリティ上、
evalはほぼ禁止レベル(特に外部入力と組み合わせるのは厳禁)。
サンプル④:安全な代替(Function + 検証つき)
💡 学び
どうしても動的にコードを扱いたい場合は、Function コンストラクタや安全なサンドボックスを利用する。
🧠 コード
function safeEval(expr) {
// 数字・演算子・括弧以外を禁止する簡易フィルタ
if (!/^[\d+\-*/().\s]+$/.test(expr)) {
throw new Error("不正な文字が含まれています");
}
const func = new Function("return " + expr);
return func();
}
console.log(safeEval("10 + 20 * 3")); // ✅ 70
console.log(safeEval("(5 + 3) * 2")); // ✅ 16
console.log(safeEval("alert('XSS')")); // ❌ エラー(検出)
JavaScript🔍 結果と解説
Functionコンストラクタで式を評価しても、ローカルスコープを汚染しない。- さらに正規表現で文字列チェックを入れることで、
安全な範囲内だけ評価できるよう制御できます。
まとめ:安全なコードの考え方
| テーマ | 内容 |
|---|---|
| ✅ クロージャ | 外部スコープの値を安全に保持できる |
| ⚠️ eval | 外部スコープは失われ、しかも危険(セキュリティリスク) |
| 💀 悪用例 | ユーザー入力を eval() で処理すると乗っ取り可能 |
| 🛡️ 安全策 | Function() + 入力検証 or 専用の評価ライブラリを使う |
ブラウザで動作するHTML実験ページ
内容構成
| セクション | 内容 |
|---|---|
| 🔹 ① 安全なクロージャ | 値を外から守る方法 |
🔹 ② クロージャ喪失 (toString + eval) | スコープが消える様子 |
🔹 ③ 危険な eval | 実行中に警告を表示(サンドボックス化) |
🔹 ④ 安全な代替 (Function + 検証) | 安全に式を評価 |
See the Pen Learning Experiments with Closures and eval by MONO365 -Color your days- (@monoqlo365) on CodePen.
このページでできること
| セクション | 実験内容 | 学べること |
|---|---|---|
| ① | プライベート変数の保持 | クロージャの仕組み |
| ② | toString + eval のスコープ喪失 | クロージャは文字列化できない |
| ③ | 悪意ある eval の防御 | eval() の危険性 |
| ④ | Function + 検証 | 安全な代替実装方法 |


