JavaScript | Function コンストラクタを使って関数を定義する

JavaScript JavaScript
スポンサーリンク

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
JavaScript

Function コンストラクタ(今回の主役)

  • 特徴: 文字列から関数を作る特殊な方法。基本的には「知っていれば十分」。
  • 書き方:
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
  • チャレンジ: 上記を「安全な代替案」で書き直してみてください(関数やスイッチで条件を定義)。
タイトルとURLをコピーしました