eval()は使わない方が良い? 安全なコードを書くためのヒント
JavaScript の eval() はいつ悪くないのか?
しかし、いくつかの限定的な状況下では、eval() の使用が正当化される場合もあります。 以下、そのようなケースをいくつか紹介します。
信頼できるコードのみを実行する場合
eval() で実行するコードが完全に信頼できる場合、セキュリティ上のリスクは存在しません。例えば、自社開発のコードや、厳格なテストを行ったオープンソースのコードを実行する場合などが考えられます。
コードを動的に生成する場合
テンプレートエンジンやコンパイラなどのツールで、コードを動的に生成する場合に、eval() が役立つことがあります。ただし、生成されたコードが安全であることを保証する必要があります。
特殊な処理を行う場合
eval() を使って、通常では不可能な処理を行うことができます。例えば、文字列を解析して動的に変数を生成したり、eval() 自身を再帰的に呼び出して複雑な処理を行うといったことができます。ただし、高度な技術が必要となるため、上級者向けのテクニックです。
eval() を使用する際の注意点
- 信頼できないコードは絶対に実行しない
- コードを厳密にテストする
- 安全対策を講じる
- 代替手段が存在するかどうかを検討する
eval() の代わりに、以下の代替手段を使用することを検討できます。
Function
コンストラクタeval
関数の厳格モードJSON.parse()
- テンプレートエンジン
- コンパイラ
例1:信頼できるコードを実行する
// 自社開発のコードを実行する
const code = `
function add(a, b) {
return a + b;
}
const result = add(1, 2);
console.log(result); // 3
`;
eval(code);
// テンプレートエンジンを使ってコードを動的に生成する
const template = `
function add(a, b) {
return <%= a %> + <%= b %>;
}
`;
const code = _.template(template)({ a: 1, b: 2 });
eval(code);
console.log(add(1, 2)); // 3
例3:特殊な処理を行う
// 文字列を解析して動的に変数を生成する
const str = "name";
const variable = eval(str);
console.log(variable); // "name"
これらのサンプルコードは、あくまでも参考として使用してください。 eval() 関数は危険を伴う可能性があるため、実際に使用する場合は、上記の注意点と代替手段を理解した上で、慎重に判断する必要があります。
eval() 関数の代替手段
Function
コンストラクタを使って、文字列から関数オブジェクトを作成することができます。
const code = `
function add(a, b) {
return a + b;
}
`;
const add = new Function(code);
console.log(add(1, 2)); // 3
eval
関数の厳格モードでは、ローカルスコープに新しい変数を生成することができません。
// 厳格モードで eval を実行する
const code = `
var a = 1;
b = 2;
`;
eval(code, { strict: true });
console.log(a); // 1
console.log(b); // ReferenceError: b is not defined
JSON 形式の文字列を解析して、JavaScript オブジェクトに変換することができます。
const json = `
{
"name": "John Doe",
"age": 30
}
`;
const object = JSON.parse(json);
console.log(object.name); // "John Doe"
console.log(object.age); // 30
テンプレートエンジンを使って、動的に HTML コードや JavaScript コードを生成することができます。
// Handlebars テンプレートエンジンを使って HTML コードを生成する
const template = `
<h1>{{name}}</h1>
<p>{{age}}</p>
`;
const data = {
name: "John Doe",
age: 30
};
const html = Handlebars.compile(template)(data);
console.log(html); // <h1>John Doe</h1><p>30</p>
JavaScript コードを別の言語にコンパイルすることで、eval() 関数を使用せずにコードを実行することができます。
// Babel を使って JavaScript コードを TypeScript にコンパイルする
const code = `
function add(a, b) {
return a + b;
}
`;
const typescript = Babel.transform(code, { presets: ["typescript"] }).code;
console.log(typescript); // function add(a: number, b: number): number {
// return a + b;
// }
これらの方法は、eval() 関数よりも安全で、読みやすいコードを書くことができます。
どの方法を使用するかは、状況によって異なります。 コードの内容、実行環境、セキュリティ要件などを考慮して、最適な方法を選択してください。
javascript coding-style eval