JavaScriptの関数:定義と呼び出し
2025-07-28はじめに
JavaScriptの関数は、一連の処理をまとめて名前を付けた「再利用できる命令のかたまり」です。
引数を受け取って処理し、結果を返すことができます。
コードの重複を減らし、プログラムを整理するために使います。
関数の基本概念
関数はJavaScriptにおける重要な構成要素で、特定のタスクを実行するコードブロックです。
関数を使うことで、コードの再利用性、可読性、保守性が向上します。
例えば以下のような関数の定義と呼び出しがあります。
// 関数宣言
function greet(name) {
return `こんにちは、${name}さん!`;
}
// 呼び出し
console.log(greet('太郎')); // こんにちは、太郎さん!

関数にすることで以下の利点を得ることができます。
関数の利点
- コードの再利用: 同じ処理を何度も書かなくて済む
- モジュール化: プログラムを小さな機能単位に分割できる
- 保守性向上: 変更が必要な場合、1箇所を修正するだけで済む
関数の定義方法
関数を使うためには、まず関数を定義(作成)し、その後呼び出して実行する手順が必要です。
関数定義の種類と特徴
| 定義方法 | 構文例 | 巻き上げ | 再代入 | thisの扱い | 特徴 | 使用場面 |
|---|---|---|---|---|---|---|
| 関数宣言 | function add(a, b) { return a + b; } | ○ (可能) | × (不可) | 呼び出し元に依存 | – コード内どこでも呼び出し可能 – 最も基本的な定義方法 – ブロックスコープの影響を受けない | 汎用的な関数 再利用性の高い関数 |
| 関数式 | const add = function(a, b) { return a + b; }; | × (不可) | △ (constの場合は不可) | 呼び出し元に依存 | – 変数に代入して定義 – 匿名関数も可能 – スコープの制御が容易 | コールバック関数 即時関数(IIFE) |
| アロー関数 | const add = (a, b) => a + b; | × (不可) | △ (constの場合は不可) | lexicalスコープを継承 | – 簡潔な記述 – thisを束縛しない – コンストラクタとして使用不可 – argumentsオブジェクトなし | コールバック メソッド内の関数 thisの固定が必要な場合 |
それぞれの宣言方法について詳細に見ていきます。
1. 関数宣言(Function Declaration)
JavaScriptで最も初歩的な関数宣言は、関数宣言(function宣言)と呼ばれる書き方です。
// 関数宣言
function greet(name) {
return `こんにちは、${name}さん!`;
}
// 呼び出し
console.log(greet('太郎')); // こんにちは、太郎さん!
特徴:
- ホイスティングされる(定義前に呼び出せる)
- ブロックスコープではなく関数スコープ
2. 関数式(Function Expression)
関数式は、関数を変数に代入する方法で、関数宣言とは違い「変数名を使って関数を呼び出す」形になります。
// 関数式
const greet = function(name) { // greet変数に関数を代入する
return `こんにちは、${name}さん!`;
};
// 呼び出し
console.log(greet('花子')); // こんにちは、花子さん!
特徴:
- 変数に代入される
- ホイスティングされない
- 無名関数(匿名関数)としても使用可能
3. アロー関数(Arrow Function)ES6
無名関数は「一時的に使いたい処理」や「イベント処理、配列の操作時のコールバック」として便利で、コードを簡潔にできます。
※コールバックについては後ほど説明します。
// アロー関数
const greet = (name) => {
return `こんにちは、${name}さん!`;
};
// 簡潔な構文(単一式の場合)
const square = x => x * x;
特徴:
thisのバインドが異なる(後述)- 簡潔な構文
- コンストラクタとして使用できない
関数の呼び出し
JavaScriptで関数を使うには、定義した関数名の後に丸括弧 () を付けて呼び出します。
このとき、必要に応じて丸括弧の中に引数を渡すことができます。
| 定義方法 | 構文例 | 巻き上げ | 再代入 | thisの扱い | 特徴 | 使用場面 |
|---|---|---|---|---|---|---|
| メソッド定義 | const obj = { add(a, b) { return a + b; } }; | × (不可) | △ (オブジェクトごとなら可能) | 所属オブジェクト | – オブジェクトのプロパティとして定義 – 簡潔なメソッド記法 – 算出プロパティ名と併用可能 | オブジェクトのメソッド クラス内メソッド |
| Functionコンストラクタ | const add = new Function('a', 'b', 'return a + b;'); | × (不可) | ○ (可能) | グローバルスコープ | – 文字列から関数を生成 – パフォーマンスが低い – セキュリティリスクあり | 動的な関数生成 JSONPなど特殊な用途 |
| ジェネレータ関数 | function* gen() { yield 1; } | ○ (可能) | × (不可) | 呼び出し元に依存 | – 反復処理の制御 – yieldで値を返す – 状態を保持 | 非同期処理 大量データの逐次処理 |
基本的な呼び出し
定義した関数名の後に丸括弧 () を付けて呼び出します。
function add(a, b) {
return a + b;
}
const result = add(3, 5); // 8
メソッドとしての呼び出し
変数に格納された関数を呼び出すとは、関数を代入した変数名に続けて括弧 () を記述します。
const calculator = {
add: function(a, b) {
return a + b;
}
};
calculator.add(2, 3); // 5
コンストラクタとしての呼び出し
new演算子と組み合わせて使用され、新しいオブジェクトを生成し、初期化する役割を担います。
function Person(name) {
this.name = name;
}
const person = new Person('太郎');
間接的な呼び出し
関数名の後に直接 () を付けて実行するのではなく、関数を別の変数に代入したり、他の関数の引数として渡したりして、あとから呼び出す方法です。
function greet() {
console.log(`こんにちは、${this.name}さん!`);
}
const user = { name: '花子' };
greet.call(user); // こんにちは、花子さん!
パラメータと引数
パラメータ:関数を定義するときに、処理のために受け取る変数の名前のこと。
引数:関数を呼び出すときに、パラメータに渡す具体的な値のこと。
| パラメータタイプ | 構文例 | 特徴 | 使用場面 |
|---|---|---|---|
| 必須パラメータ | function(a, b) | – 呼び出し時に必須 – 不足時はundefined | 基本的な関数定義 |
| デフォルトパラメータ | function(a = 1, b = 2) | – 値が未提供時のデフォルト値 – ES6で導入 | オプショナルな引数 |
| 残余パラメータ | function(...args) | – 任意の数の引数を配列で受け取る – 最後のパラメータのみ使用可能 | 可変長引数関数 |
| 分割代入パラメータ | function({x, y}) | – オブジェクトのプロパティを直接受け取る – 設定オブジェクトに有用 | 設定オブジェクトの受け取り |
必須パラメータ
関数の呼び出し時に必須となる引数です。
function add(a, b) {
return a + b;
}
console.log(add(3, 5)); // 8
デフォルトパラメータ(ES6)
デフォルトパラメータは、関数のパラメータに初期値を設定できるES6の機能です。
呼び出し時に引数が渡されなかったり、undefinedの場合に、あらかじめ指定した値が使われます。
function greet(name = 'ゲスト') {
console.log(`こんにちは、${name}さん!`);
}
greet(); // こんにちは、ゲストさん!
greet('太郎'); // こんにちは、太郎さん!
残余パラメータ(Rest Parameters)
残余パラメータ(Rest Parameters)は、関数の引数をまとめて配列として受け取るES6の機能です。
関数が不特定多数の引数を扱いたいときに便利です。
function sum(...numbers) {
return numbers.reduce((acc, num) => acc + num, 0);
}
console.log(sum(1, 2, 3)); // 6
console.log(sum(1, 2, 3, 4, 5)); // 15
引数の分割代入
引数の分割代入とは、関数の引数としてオブジェクトや配列を受け取り、その中の値を直接変数に取り出す書き方です。
コードがシンプルで見やすくなります。
function printUser({ name, age }) {
console.log(`${name}さんは${age}歳です`);
}
const user = { name: '太郎', age: 25 };
printUser(user); // 太郎さんは25歳です
戻り値とスコープ
戻り値(return値):関数が処理結果を呼び出し元に返す値のこと
スコープ:変数や関数が「見える(アクセスできる)」範囲のこと
戻り値の重要性
戻り値(return値)は、関数が処理結果を呼び出し元に返す値のことです。
returnキーワードで指定し、戻り値があることで関数の結果を他の処理に使えます。
// 戻り値がある関数
function add(a, b) {
return a + b;
}
// 戻り値がない関数(undefinedを返す)
function noReturn() {
// 何も返さない
}
スコープの挙動
スコープは、変数や関数が「見える(アクセスできる)」範囲のことです。
関数内で宣言した変数はその関数内だけ有効(ローカルスコープ)で、外からは見えません。
グローバルスコープはプログラム全体で有効な範囲です。
let globalVar = 'グローバル';
function testScope() {
let localVar = 'ローカル';
console.log(globalVar); // アクセス可能
console.log(localVar); // アクセス可能
}
testScope();
console.log(globalVar); // アクセス可能
// console.log(localVar); // エラー(アクセス不可)
応用関数
高階関数(Higher-Order Function)
高階関数(Higher-Order Function)とは、関数を引数に取ったり、関数を返したりする関数のことです。

処理を柔軟に組み合わせるのに使います。
// 関数を引数に取る関数
function operate(a, b, operation) {
return operation(a, b);
}
function add(x, y) { return x + y; }
function multiply(x, y) { return x * y; }
console.log(operate(3, 4, add)); // 7
console.log(operate(3, 4, multiply)); // 12
コールバック関数
コールバック関数(Callback Function)は、他の関数に渡されて実行される関数のことです。
非同期処理やイベント処理でよく使われます。

コールバックとは、ある関数を呼び出す際に、別の関数を引数として渡し、その引数として渡された関数を、元の関数の中で後で実行させる仕組みのことです。
// コールバックを使用した非同期処理の模倣
function fetchData(callback) {
setTimeout(() => {
callback('データ');
}, 1000);
}
fetchData(data => {
console.log('取得したデータ:', data);
});
コールバック関数については別記事にて説明しています。コールバック関数について
即時実行関数式(IIFE)
即時実行関数式(IIFE: Immediately Invoked Function Expression)は、関数を定義すると同時にすぐ実行する仕組みです。

- 一度だけ実行される
- 変数のスコープを限定してグローバル汚染を防ぐ
- 古いJavaScriptでもモジュールのように使える
// 定義と同時に実行
(function() {
console.log('即時実行');
})();
// スコープを隔離する用途で使用
(function() {
let privateVar = '外部からアクセス不可';
// ここでの変数は外部から見えない
})();
再帰関数
再帰関数とは、自分自身を呼び出す関数のことです。

繰り返し処理や階層的なデータ処理に使われます。
ポイントは「終了条件(ベースケース)」を必ず設けて、無限に呼び出され続けないようにすることです。
// 階乗を計算する再帰関数
function factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
console.log(factorial(5)); // 120
関数のベストプラクティス
- 単一責任の原則: 1つの関数は1つのことだけを行う
- 説明的な名前: 関数名から機能がわかるように
- 適切な長さ: 一般的に20行以内が目安
- 副作用を最小限に: 外部状態を変更しない純粋関数を目指す
- デフォルト引数を使用: 未定義エラーを防ぐ
- 適切なコメント: 複雑なロジックには説明を追加
まとめ
関数はプログラムの基本単位で、繰り返し使える便利な仕組み。
目的ごとに処理を分けて書くことで、読みやすく修正しやすいコードになります。
関数を覚えることはJavaScriptの理解に欠かせません。
演習問題
初級問題(3問)
- 次の関数を関数式とアロー関数で書き換えなさい。
function multiply(a, b) {
return a * b;
}
- 次の関数呼び出しの出力結果は?
function sayHello(name = 'ゲスト') {
console.log(`こんにちは、${name}さん!`);
}
sayHello();
sayHello('太郎');
- 次の関数の間違いを指摘し、修正しなさい。
function sum(a, b) {
console.log(a + b);
}
const result = sum(2, 3);
console.log(result);
中級問題(6問)
- 次の関数を残余パラメータを使用して書き換えなさい。
function sum(a, b, c) {
return a + b + c;
}
- 次のコードの出力結果とその理由を説明しなさい。
let x = 10;
function updateX() {
x = 20;
}
updateX();
console.log(x);
- 引数として受け取った数値が 正の数か負の数かを判定する関数 isPositive を作成しなさい。ゼロの場合は "zero"、正の数は "positive"、負の数は "negative" を返すようにしてください。
- 次の高階関数を使用して、配列の各要素を2倍にするコードを書きなさい。
function mapArray(arr, transform) {
const result = [];
for (let item of arr) {
result.push(transform(item));
}
return result;
}
- オブジェクトを受け取り、そのプロパティをすべて表示する関数
printObjectを作成しなさい。 - 次の再帰関数の動作を説明し、
factorial(4)の呼び出し時の実行フローを追跡しなさい。
function factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
上級問題(3問)
- カリー化された関数
addを作成しなさい。以下のように動作するものとします。
console.log(add(2)(3)(4)()); // 9
console.log(add(1)(2)()); // 3
- メモ化を実装したフィボナッチ関数を作成しなさい。再帰計算の効率を向上させること。
- 以下の要件を満たす関数
createCounterを実装しなさい。
const counter1 = createCounter();
console.log(counter1()); // 1
console.log(counter1()); // 2
const counter2 = createCounter(10, 5);
console.log(counter2()); // 15
console.log(counter2()); // 20
解答例
初級問題解答
- 関数式とアロー関数で書き換え
// 関数式
const multiply = function(a, b) {
return a * b;
};
// アロー関数
const multiply = (a, b) => a * b;
- 呼び出しの出力結果
こんにちは、ゲストさん!
こんにちは、太郎さん!
function sayHello(name = 'ゲスト') {
console.log(`こんにちは、${name}さん!`);
}
sayHello(); // こんにちは、ゲストさん!
sayHello('太郎'); // こんにちは、太郎さん!
- 間違いと修正
// 間違い: console.logで出力しているだけで値を返していない
// 修正例:
function sum(a, b) {
return a + b;
}
中級問題解答
- 残余パラメータを使用して書き換え
function sum(...numbers) {
return numbers.reduce((acc, num) => acc + num, 0);
}
- コードの出力結果とその理由
20
let x = 10;
function updateX() {
x = 20; // 宣言してないのでグローバル変数として認識される
}
updateX(); // 関数内でグローバル変数xを更新しているため
console.log(x);
- 正の数か負の数かを判定する関数 isPositive
function isPositive(num) {
if (num > 0) {
return "positive";
} else if (num < 0) {
return "negative";
} else {
return "zero";
}
}
- 高階関数を使用して、配列の各要素を2倍にするコード
const doubled = mapArray([1, 2, 3], x => x * 2);
// [2, 4, 6]
- プロパティをすべて表示する関数
printObject
function printObject(obj) {
for (const key in obj) {
console.log(`${key}: ${obj[key]}`);
}
}
factorial(4)の実行フロー
factorial(4)
→ 4 * factorial(3)
→ 3 * factorial(2)
→ 2 * factorial(1)
→ 1 (ベースケース)
→ 2 * 1 = 2
→ 3 * 2 = 6
→ 4 * 6 = 24
上級問題解答
- カリー化された関数
add
function add(a) {
return function(b) {
return function(c) {
return function() {
return a + b + c;
};
};
};
}
関数のカリー化とは、一回性で必要な引数を入れるのではなく、あらかじめ関数の引数を数段階に分けて、段階別に引数を自由に操作できる構造です。
- メモ化を実装したフィボナッチ関数
function fibonacci(n, memo = {}) {
if (n in memo) return
memo[n];
if (n <= 1) return n;
memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo);
return memo[n];
}
createCounter関数
javascript function createCounter(initial = 0, step = 1) {
let count = initial;
return function() {
count += step;
return count;
};
}