🌊
【基礎から学ぶ】関数の作り方と使い方を徹底解説
プログラミングにおいて、関数は最も重要な基本要素の1つです。コードの再利用性を高め、プログラムを整理するために不可欠な存在です。この記事では、関数の基本的な概念から実践的な使い方まで、初心者にもわかりやすく解説します。
関数とは?
関数は、特定の処理をまとめた「部品」のようなものです。一度作った関数は、必要なときに何度でも使うことができます。
関数を使うメリット
-
コードの再利用
- 同じ処理を何度も書く必要がない
- 変更が必要な場合も1箇所を修正するだけでよい
-
プログラムの整理
- 処理をわかりやすい単位に分割できる
- コードの見通しが良くなる
-
保守性の向上
- バグの修正が容易になる
- 機能の追加や変更がしやすくなる
関数の基本構造
JavaScriptを例に、関数の基本的な構造を見ていきましょう。
関数の宣言
// 基本的な関数の形
function greet(name) {
return "こんにちは、" + name + "さん!";
}
// 関数の使用
let message = greet("田中");
console.log(message); // "こんにちは、田中さん!"
関数の構成要素:
-
function
: 関数を定義するキーワード -
greet
: 関数名 -
(name)
: パラメータ(引数) -
return
: 戻り値を指定するキーワード
関数の種類
JavaScriptには、関数を定義する複数の方法があります。
1. 関数宣言
// 関数宣言
function add(a, b) {
return a + b;
}
console.log(add(5, 3)); // 8
2. 関数式
// 関数式
const multiply = function(a, b) {
return a * b;
};
console.log(multiply(4, 2)); // 8
3. アロー関数式
// アロー関数式(ES6以降)
const divide = (a, b) => {
return a / b;
};
// 1行で書ける場合は更にシンプルに
const subtract = (a, b) => a - b;
console.log(divide(10, 2)); // 5
console.log(subtract(10, 3)); // 7
パラメータと戻り値
パラメータの使い方
// 基本的なパラメータ
function greet(firstName, lastName) {
return `こんにちは、${lastName}${firstName}さん!`;
}
// デフォルト値の設定
function greetWithTitle(name, title = "さん") {
return `こんにちは、${name}${title}!`;
}
// 可変長引数
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(greet("太郎", "山田")); // "こんにちは、山田太郎さん!"
console.log(greetWithTitle("田中")); // "こんにちは、田中さん!"
console.log(greetWithTitle("山本", "先生")); // "こんにちは、山本先生!"
console.log(sum(1, 2, 3, 4, 5)); // 15
戻り値の使い方
// 単一の値を返す
function square(n) {
return n * n;
}
// 複数の値を返す(オブジェクトとして)
function getPersonInfo(name, age) {
return {
name: name,
age: age,
isAdult: age >= 20
};
}
// 配列を返す
function splitName(fullName) {
return fullName.split(" ");
}
console.log(square(5)); // 25
console.log(getPersonInfo("山田太郎", 25)); // { name: "山田太郎", age: 25, isAdult: true }
console.log(splitName("山田 太郎")); // ["山田", "太郎"]
スコープと変数の有効範囲
関数内で宣言された変数は、その関数の外からアクセスできません。
function calculateTotal() {
let subtotal = 1000; // この変数は関数の中でのみ有効
let tax = subtotal * 0.1;
return subtotal + tax;
}
console.log(calculateTotal()); // 1100
// console.log(subtotal); // エラー:subtotalは定義されていない
グローバル変数とローカル変数
let globalVar = "グローバル変数"; // グローバルスコープ
function showScope() {
let localVar = "ローカル変数"; // 関数スコープ
console.log(globalVar); // グローバル変数にアクセス可能
console.log(localVar); // ローカル変数にアクセス可能
}
showScope();
console.log(globalVar); // グローバル変数にアクセス可能
// console.log(localVar); // エラー:ローカル変数にはアクセス不可
実践的な関数の例
1. 配列の操作
// 配列の要素を2倍にする関数
function doubleArray(arr) {
return arr.map(num => num * 2);
}
// 配列の合計を計算する関数
function calculateSum(arr) {
return arr.reduce((sum, num) => sum + num, 0);
}
// 特定の条件で配列をフィルタリングする関数
function filterEvenNumbers(arr) {
return arr.filter(num => num % 2 === 0);
}
const numbers = [1, 2, 3, 4, 5];
console.log(doubleArray(numbers)); // [2, 4, 6, 8, 10]
console.log(calculateSum(numbers)); // 15
console.log(filterEvenNumbers(numbers)); // [2, 4]
2. オブジェクトの操作
// ユーザーオブジェクトを作成する関数
function createUser(name, age, email) {
return {
name,
age,
email,
createdAt: new Date(),
isAdult: age >= 20
};
}
// ユーザー情報をフォーマットする関数
function formatUserInfo(user) {
return `${user.name}(${user.age}歳)- ${user.email}`;
}
const user = createUser("山田太郎", 25, "yamada@example.com");
console.log(user);
console.log(formatUserInfo(user));
3. 非同期処理
// Promise を使用した非同期関数
async function fetchUserData(userId) {
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
const data = await response.json();
return data;
} catch (error) {
console.error("エラーが発生しました:", error);
return null;
}
}
// タイマー関数
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 使用例
async function main() {
console.log("処理開始");
await delay(1000);
console.log("1秒経過");
await delay(1000);
console.log("2秒経過");
}
関数の設計のベストプラクティス
1. 単一責任の原則
関数は1つのことだけを行うようにしましょう。
// 悪い例:複数の責任を持つ関数
function processUserData(user) {
validateUser(user);
saveToDatabase(user);
sendEmail(user);
}
// 良い例:責任を分割した関数
function validateUser(user) {
// ユーザーデータの検証のみを行う
}
function saveUser(user) {
// データベースへの保存のみを行う
}
function notifyUser(user) {
// メール送信のみを行う
}
2. 適切な命名
関数名は、その機能を明確に表すものにしましょう。
// 悪い例
function process(data) {
// 何を処理するのかわからない
}
// 良い例
function calculateTotalPrice(items) {
return items.reduce((total, item) => total + item.price, 0);
}
3. エラーハンドリング
関数は適切にエラーを処理する必要があります。
function divideNumbers(a, b) {
// パラメータの検証
if (typeof a !== 'number' || typeof b !== 'number') {
throw new Error('引数は数値である必要があります');
}
// ゼロ除算の防止
if (b === 0) {
throw new Error('0で除算することはできません');
}
return a / b;
}
// 使用例
try {
console.log(divideNumbers(10, 2)); // 5
console.log(divideNumbers(10, 0)); // エラーが発生
} catch (error) {
console.error('エラーが発生しました:', error.message);
}
デバッグとテスト
コンソールログを使ったデバッグ
function calculateDiscount(price, quantity) {
console.log('入力値:', { price, quantity });
let discount = 0;
if (quantity >= 10) {
discount = 0.1;
} else if (quantity >= 5) {
discount = 0.05;
}
console.log('適用される割引率:', discount);
const total = price * quantity * (1 - discount);
console.log('計算結果:', total);
return total;
}
単体テストの例
// テスト関数
function testCalculateDiscount() {
// テストケース1: 通常価格
console.assert(
calculateDiscount(100, 1) === 100,
'単品購入のテストが失敗しました'
);
// テストケース2: 5個以上で5%割引
console.assert(
calculateDiscount(100, 5) === 475,
'5個購入の割引テストが失敗しました'
);
// テストケース3: 10個以上で10%割引
console.assert(
calculateDiscount(100, 10) === 900,
'10個購入の割引テストが失敗しました'
);
console.log('すべてのテストが成功しました!');
}
まとめ
関数は、プログラミングの基本的かつ重要な要素です。以下のポイントを押さえておきましょう:
-
基本構造を理解する
- 関数の宣言方法
- パラメータと戻り値の使い方
- スコープの概念
-
適切な設計を心がける
- 単一責任の原則
- 明確な命名
- エラーハンドリング
-
実践的な使い方を学ぶ
- 配列やオブジェクトの操作
- 非同期処理
- デバッグとテスト
関数の基本を理解し、適切に使用することで、より保守性が高く、再利用可能なコードを書くことができます。
次のステップ
関数の基本を理解したら、以下の記事も参考にしてください:
Discussion
関数式を載せた上で アロー関数を するのであれば
分類の意味も兼ねて アロー関数よりも アロー関数式表記で記述したほうが良いのではないでしょうか?
ご指摘いただき、ありがとうございます!
仰るとおり、「関数式」と「アロー関数(式)」の記述方法が混ざってしまい、少々わかりづらくなっていましたね。
ご提案いただいたように、
のように、分類と表記方法を明確に整理して修正します。読み手が混乱しないように、記事も修正しておきますね。
丁寧なフィードバックで大変助かりました!
引き続きよろしくお願いいたします。