JavaScript の Function コンストラクタを、初心者向けにじっくり解説
はじめの一歩として、まず「普通の関数の作り方」と「Function コンストラクタの作り方」を比べながら、何が違うのか・いつ使うのかをイメージできるように説明します。途中で手を動かせる練習問題も入れます。
関数の基本と、3つの作り方
普通の関数宣言(おすすめの基本形)
- 特徴: 読みやすく、エラーも見つけやすい。ほとんどの場面でこれを使えばOK。
- 書き方:
function add(x, y) {
return x + y;
}
console.log(add(3, 4)); // 7
JavaScriptアロー関数(短くスマート)
- 特徴: 1行で書けてスッキリ。最近のコードはこれが多い。
- 書き方:
const add = (x, y) => x + y;
console.log(add(3, 4)); // 7
JavaScriptFunction コンストラクタ(今回の主役)
- 特徴: 文字列から関数を作る特殊な方法。基本的には「知っていれば十分」。
- 書き方:
const add = new Function("x", "y", "return x + y;");
console.log(add(3, 4)); // 7
JavaScript- ポイント: 引数や処理を「文字列」で渡すのが最大の違い。
newは省略してFunction(...)としても動きます。
Function コンストラクタの仕組み
どう動くの?
- 文字列から関数を作る:
"x", "y", "return x + y;"のように、関数の中身を文字列で渡します。JavaScript がその文字列をコードとして「解釈」して関数を生成します。
例1:複数の処理を書く
const greet = new Function(
"name",
`
const message = "こんにちは、" + name + "さん!";
return message;
`
);
console.log(greet("田中")); // こんにちは、田中さん!
JavaScript- ポイント: 文字列の中なので、改行や
;を自分で書きます。テンプレートリテラル(バッククォート)を使うと複数行が書きやすいです。
例2:引数が可変な関数を作る
const sum = new Function(
"numbers",
`
let total = 0;
for (const n of numbers) total += n;
return total;
`
);
console.log(sum([1, 2, 3, 4])); // 10
JavaScriptいつ使うの?実務ではほぼ使わない理由
デメリットが大きい
- 可読性が低い: 文字列の中にコードを書くので、ミスが見つけにくい。
- エディタ支援が弱い: オート補完やエラー検知が効きづらい。
- セキュリティリスク: 外部から受け取った文字列をそのまま使うと、意図しないコードが実行される危険がある。
つまり
- 通常は「関数宣言」か「アロー関数」を使うべき。
- Function コンストラクタは「動的にコードを作らないといけない特殊ケース」以外では避けるのが安全。
手を動かす例題で理解する
例題1:四則演算関数を文字列から生成
- 目標: 文字列で受け取った演算子に応じて関数を作る。
function createOperator(op) {
// op は "+", "-", "*", "/" のいずれか
return new Function("a", "b", `return a ${op} b;`);
}
const plus = createOperator("+");
console.log(plus(10, 5)); // 15
const div = createOperator("/");
console.log(div(20, 4)); // 5
JavaScript- 学び: 「動的に関数を作る」ことはできるが、入力(op)が想定外だと危険。実務なら厳格にチェックするか、分岐で書くほうが安全。
例題2:テンプレート文字列で整形関数
- 目標: 任意の形の文字列を生成する関数を作る。
function createTemplate(templateBody) {
// templateBody 例: "`${last}, ${first}`"
return new Function("first", "last", `return ${templateBody};`);
}
const fullName = createTemplate("`${last} ${first}`");
console.log(fullName("Taro", "Yamada")); // Yamada Taro
JavaScript- 学び: バッククォートで中身をわかりやすくできるが、やはり入力の検証が必須。
例題3:安全な代替の考え方
- 目標: Function コンストラクタを使わずに同じことを達成する。
// 演算子ごとに事前に用意する(推奨)
const ops = {
"+": (a, b) => a + b,
"-": (a, b) => a - b,
"*": (a, b) => a * b,
"/": (a, b) => a / b
};
function safeCreateOperator(op) {
if (!ops[op]) throw new Error("不正な演算子です");
return ops[op];
}
console.log(safeCreateOperator("+")(2, 3)); // 5
JavaScript- 学び: 動的生成を避けることで、読みやすさ・安全性が高まる。
よくあるつまずきポイント
- 文字列中の引用符ミス:
” と ‘ とのどれを使うか混乱しやすい。テンプレートリテラル()を使うと複数行や変数埋め込みが楽。 - スコープの違い:
Function コンストラクタで作った関数は、作成時の外側の変数に直接アクセスできないことがある(クロージャの挙動が通常の関数と異なると感じる場合がある)。外部値は引数で渡すのが安全。 - 入力の安全性:
ユーザー入力をそのままコードにしない。必ず検証・サニタイズするか、代替手法を選ぶ。
学習の指針とまとめ
- まずは基本の関数宣言とアロー関数に慣れる。
- Function コンストラクタは「こういうこともできる」知識として持ち、実務では原則使わない。
- もし使うなら、入力の検証・例外処理・テストを必ずセットで。
ミニ課題(5分)
- 課題: 配列のフィルタ条件を文字列で指定して、合格者だけ抽出する関数を作ってみる。
function createFilter(conditionBody) {
// conditionBody 例: "score >= 80 && passed === true"
return new Function("item", `const { score, passed } = item; return ${conditionBody};`);
}
const students = [
{ name: "A", score: 85, passed: true },
{ name: "B", score: 72, passed: true },
{ name: "C", score: 90, passed: false }
];
const filter = createFilter("score >= 80 && passed === true");
const result = students.filter(filter);
console.log(result); // [{ name: "A", score: 85, passed: true }]
JavaScript- チャレンジ: 上記を「安全な代替案」で書き直してみてください(関数やスイッチで条件を定義)。
