チュートリアル

JavaScript基礎:関数

JavaScript入門関数
広告エリア

関数の定義

関数宣言

function greet(name) {
  return `こんにちは、${name}さん!`;
}

console.log(greet("太郎"));  // こんにちは、太郎さん!

// 巻き上げ(hoisting)により、宣言前に呼び出し可能
sayHello();  // OK

function sayHello() {
  console.log("Hello!");
}

関数式

const greet = function(name) {
  return `こんにちは、${name}さん!`;
};

// 巻き上げされない
// sayHi();  // エラー
const sayHi = function() {
  console.log("Hi!");
};

アロー関数(ES6)

// 基本形
const greet = (name) => {
  return `こんにちは、${name}さん!`;
};

// 引数が1つなら括弧を省略可能
const greet = name => {
  return `こんにちは、${name}さん!`;
};

// 1行なら{}とreturnを省略可能
const greet = name => `こんにちは、${name}さん!`;

// 引数がないとき
const sayHello = () => "Hello!";

// オブジェクトを返すとき(括弧が必要)
const createUser = name => ({ name, createdAt: new Date() });

引数

デフォルト引数

function greet(name = "ゲスト") {
  return `こんにちは、${name}さん!`;
}

console.log(greet());       // こんにちは、ゲストさん!
console.log(greet("太郎")); // こんにちは、太郎さん!

残余引数(Rest Parameters)

function sum(...numbers) {
  return numbers.reduce((acc, n) => acc + n, 0);
}

console.log(sum(1, 2, 3));     // 6
console.log(sum(1, 2, 3, 4, 5)); // 15

// 他の引数と組み合わせ
function log(level, ...messages) {
  console.log(`[${level}]`, ...messages);
}

log("INFO", "ユーザー", "ログイン");

分割代入(引数)

function printUser({ name, age }) {
  console.log(`${name}(${age}歳)`);
}

const user = { name: "太郎", age: 25 };
printUser(user);  // 太郎(25歳)

// デフォルト値付き
function createUser({ name, role = "user" } = {}) {
  return { name, role };
}

コールバック関数

function doSomething(callback) {
  console.log("処理を実行中...");
  callback();
}

doSomething(() => {
  console.log("コールバック実行!");
});

// 配列メソッドでよく使う
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
const evens = numbers.filter(n => n % 2 === 0);

クロージャ

function createCounter() {
  let count = 0;  // この変数は外部からアクセス不可

  return {
    increment() {
      count++;
      return count;
    },
    decrement() {
      count--;
      return count;
    },
    getCount() {
      return count;
    }
  };
}

const counter = createCounter();
console.log(counter.increment());  // 1
console.log(counter.increment());  // 2
console.log(counter.decrement());  // 1
console.log(counter.getCount());   // 1
// console.log(count);  // エラー(アクセス不可)

クロージャの活用例

// 関数を生成する関数
function multiplyBy(factor) {
  return (number) => number * factor;
}

const double = multiplyBy(2);
const triple = multiplyBy(3);

console.log(double(5));  // 10
console.log(triple(5));  // 15

// プライベート変数
function createBankAccount(initialBalance) {
  let balance = initialBalance;

  return {
    deposit(amount) {
      balance += amount;
      return balance;
    },
    withdraw(amount) {
      if (amount > balance) {
        throw new Error("残高不足");
      }
      balance -= amount;
      return balance;
    },
    getBalance() {
      return balance;
    }
  };
}

高階関数

// 関数を返す関数
function createGreeter(greeting) {
  return function(name) {
    return `${greeting}, ${name}!`;
  };
}

const sayHello = createGreeter("Hello");
const sayHi = createGreeter("Hi");

console.log(sayHello("太郎"));  // Hello, 太郎!
console.log(sayHi("花子"));     // Hi, 花子!

// 関数を受け取る関数
function repeat(n, action) {
  for (let i = 0; i < n; i++) {
    action(i);
  }
}

repeat(3, i => console.log(`${i}回目`));

thisの挙動

const user = {
  name: "太郎",
  greet() {
    console.log(`こんにちは、${this.name}です`);
  },
  greetArrow: () => {
    console.log(`こんにちは、${this.name}です`);  // thisが違う
  }
};

user.greet();       // こんにちは、太郎です
user.greetArrow();  // こんにちは、undefinedです

// コールバックでのthis問題
const user2 = {
  name: "花子",
  friends: ["太郎", "次郎"],
  showFriends() {
    // アロー関数はthisを継承する
    this.friends.forEach(friend => {
      console.log(`${this.name}の友達: ${friend}`);
    });
  }
};

user2.showFriends();
// 花子の友達: 太郎
// 花子の友達: 次郎

即時実行関数(IIFE)

// グローバルスコープを汚染しない
(function() {
  const privateVar = "秘密";
  console.log(privateVar);
})();

// console.log(privateVar);  // エラー

// アロー関数版
(() => {
  console.log("即時実行");
})();

まとめ

  • 関数宣言は巻き上げされる、関数式はされない
  • アロー関数は簡潔でthisを継承する
  • ...argsで可変長引数を受け取れる
  • クロージャで変数をカプセル化できる
  • コールバックと高階関数はJavaScriptの基本

次回は配列とオブジェクトについて学びます。

広告エリア