JavaScriptのアロー関数:基本と活用

2025-07-28

アロー関数とは

アロー関数(Arrow Function)はES6(ECMAScript 2015)で導入された、より簡潔な関数記法です。=>の見た目から「矢印関数」とも呼ばれます。

基本的な構文

// 従来の関数式
const add = function(a, b) {
  return a + b;
};

// アロー関数
const add = (a, b) => {
  return a + b;
};

アロー関数の特徴

1. 簡潔な構文

単一式の場合return{}を省略可能


// 従来
const square = function(x) {
  return x * x;
};

// アロー関数
const square = x => x * x;

引数が1つの場合()を省略可能

const double = x => x * 2;

2. thisの扱い

アロー関数は独自のthisを持たず、外側のスコープのthisを継承します(レキシカルスコープ)。

const person = {
  name: '太郎',
  traditionalFunc: function() {
    console.log(this.name); // '太郎'
  },
  arrowFunc: () => {
    console.log(this.name); // undefined(外側のthisを参照)
  }
};

3. コンストラクタとして使用不可

const Person = (name) => {
  this.name = name; // TypeError
};
// new Person('太郎'); // エラー

4. argumentsオブジェクトが無い

const traditional = function() {
  console.log(arguments);
};

const arrow = () => {
  // console.log(arguments); // エラー
  console.log(...arguments); // 残余パラメータを使用
};

traditional(1, 2, 3); // Arguments(3) [1, 2, 3]
// arrow(1, 2, 3); // エラー

アロー関数の様々な書き方

基本形

const func = (arg1, arg2) => {
  // 処理
  return result;
};

引数なし

const greet = () => {
  console.log('Hello!');
};

単一引数

const square = x => {
  return x * x;
};

単一式(暗黙のreturn)

const square = x => x * x;

オブジェクトリテラルを返す

const createUser = (name, age) => ({
  name: name,
  age: age
});

// プロパティ名の短縮記法
const createUser = (name, age) => ({ name, age });

アロー関数の適切な使用場面

推奨するケース

  1. コールバック関数
   const numbers = [1, 2, 3];
   const doubled = numbers.map(x => x * 2);
  1. thisのバインドが必要ない場合
   const button = document.querySelector('button');
   button.addEventListener('click', () => {
     console.log('Clicked!');
   });
  1. 簡潔な一行関数
   const isEven = num => num % 2 === 0;

避けるべきケース

  1. メソッド定義
   // 👎 非推奨
   const obj = {
     value: 10,
     getValue: () => this.value // undefined
   };

   // 👍 推奨
   const obj = {
     value: 10,
     getValue() { return this.value; }
   };
  1. コンストラクタ関数
   // 👎 できない
   const Person = name => {
     this.name = name;
   };

   // 👍 関数宣言を使用
   function Person(name) {
     this.name = name;
   }
  1. イベントハンドラでthisが必要な場合
   // 👎 thisが期待通りにならない
   button.addEventListener('click', () => {
     console.log(this); // 期待するthisではない
   });

   // 👍 通常の関数を使用
   button.addEventListener('click', function() {
     console.log(this); // button要素
   });

アロー関数と通常関数の比較

特徴アロー関数通常関数
thisの扱いレキシカルスコープ呼び出し元に依存
argumentsオブジェクト❌ 無し✅ 有り
コンストラクタとして使用❌ 不可✅ 可能
簡潔な構文✅ 可能❌ 不可
メソッド定義⚠️ 不適✅ 適切
ホイスティング❌ 無し✅ 有り(関数宣言)

アロー関数の実践例

配列操作

const numbers = [1, 2, 3, 4, 5];

// 偶数のみフィルタリング
const evens = numbers.filter(n => n % 2 === 0);

// 各要素を2乗
const squares = numbers.map(n => n * n);

// 合計を計算
const sum = numbers.reduce((acc, n) => acc + n, 0);

非同期処理

// Promiseチェーン
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => {
    console.log(data);
  })
  .catch(error => console.error(error));

高階関数

const createMultiplier = factor => x => x * factor;

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

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

アロー関数の落とし穴

オブジェクトリテラルの返却

// 👎 動かない({}がブロックと解釈される)
const createUser = (name, age) => { name, age };

// 👍 正しい書き方
const createUser = (name, age) => ({ name, age });

複数行の処理

// 複数行の場合は明示的なreturnが必要
const process = (x, y) => {
  const sum = x + y;
  const product = x * y;
  return { sum, product };
};

デバッグ時の匿名性

// 匿名関数としてスタックトレースに表示される
const func = () => {
  throw new Error('エラー発生');
};
func(); // スタックトレースで"func"ではなく"anonymous"と表示

演習問題

初級問題(3問)

  1. 次の関数をアロー関数に書き換えなさい。
   function multiply(a, b) {
     return a * b;
   }
  1. 次のアロー関数の呼び出し結果は?
   const greet = name => `こんにちは、${name}さん!`;
   console.log(greet('太郎'));
  1. 次のコードの間違いを修正しなさい。
   const numbers = [1, 2, 3];
   const squared = numbers.map(function(x) {
     return x * x;
   });

中級問題(6問)

  1. 次のアロー関数を通常の関数に書き換えなさい。
   const getFullName = (firstName, lastName) => `${firstName} ${lastName}`;
  1. 次のオブジェクトのメソッドをアロー関数に変更した場合の問題点を指摘しなさい。
   const counter = {
     count: 0,
     increment: function() {
       this.count++;
     }
   };
  1. 次の配列から偶数のみを抽出し、それぞれを2倍した配列を作成しなさい(アロー関数を使用)。
   const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  1. 次のアロー関数を1行で書き換えなさい。
   const isPositive = number => {
     return number > 0;
   };
  1. 次のコードの出力結果とその理由を説明しなさい。
   const obj = {
     value: 10,
     traditional: function() {
       console.log(this.value);
     },
     arrow: () => {
       console.log(this.value);
     }
   };

   obj.traditional();
   obj.arrow();
  1. 次の高階関数を使用して、文字列を反転させる関数を作成しなさい。
   const createTransformer = transform => str => transform(str);

上級問題(3問)

  1. カリー化された加算関数addをアロー関数で実装しなさい。
console.log(add(2)(3)(4)()); // 9
  1. 次の動作をするpipe関数をアロー関数で実装しなさい。
const double = x => x * 2; 
const square = x => x * x; 
const piped = pipe(double, square); 
console.log(piped(5)); // 100 (5*2 = 10, 10^2 = 100)
  1. アロー関数のみを使用して、次のような動作をするcreateCounter関数を実装しなさい。
javascript const counter = createCounter(); 
console.log(counter()); // 1 
console.log(counter()); // 2 
console.log(counter()); // 3

解答例

初級問題解答

  1. アロー関数に書き換え
   const multiply = (a, b) => a * b;
  1. 呼び出し結果
   こんにちは、太郎さん!
    const greet = name => `こんにちは、${name}さん!`;
    console.log(greet('太郎')); // こんにちは、太郎さん!
  1. アロー関数を使用した修正
   const squared = numbers.map(x => x * x);

中級問題解答

  1. 通常の関数に書き換え
   function getFullName(firstName, lastName) {
     return `${firstName} ${lastName}`;
   }
  1. 問題点の指摘
   // アロー関数にするとthisが期待通りにならない
   const counter = {
     count: 0,
     increment: () => {
       this.count++; // thisはcounterオブジェクトを指さない
     }
   };
  1. 偶数の2倍
   const result = numbers
     .filter(n => n % 2 === 0)
     .map(n => n * 2);
  1. 1行で書き換え
   const isPositive = number => number > 0;
  1. 出力結果と理由
   10
   undefined
    const obj = {
        value: 10,
        traditional: function() {
            console.log(this.value);    // obj.valueの値を参照
        },
        arrow: () => {
            console.log(this.value);    // thisは外側のスコープを参照するため、undefinedになる
        }
    };

    obj.traditional();
    obj.arrow();
  1. 文字列反転関数
   const reverseString = createTransformer(str => 
     str.split('').reverse().join('')
   );
   console.log(reverseString('hello')); // 'olleh'

上級問題解答

  1. カリー化加算関数
const add = a => b => c => () => a + b + c;
  1. pipe関数
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
  1. createCounter関数
javascript const createCounter = () => { 
    let count = 0;
    return () => ++count;
};