
JavaScriptのアロー関数:基本と活用
2025-07-28はじめに
アロー関数は通常の関数よりも短い記法で書け、特に無名関数やコールバックに便利です。最大の違いはthis
の扱いで、アロー関数は外側のスコープのthis
を継承し、通常関数のように呼び出し方でthis
が変わることがありません。また、アロー関数はコンストラクタとして使えず、new
での呼び出しができません。これらの特徴を理解し使い分けることが重要です。
アロー関数とは
アロー関数(Arrow Function)はES6(ECMAScript 2015)で導入された、より簡潔な関数記法です。=>
の見た目から「矢印関数」とも呼ばれます。
基本的な構文
アロー関数は、function
キーワードの代わりに矢印(=>
)を使って関数を定義します。まず、引数が1つの場合は丸括弧を省略できますが、複数の場合は括弧で囲みます。
// 従来の関数式
const add = function(a, b) {
return a + b;
};
// アロー関数
const add = (a, b) => {
return a + b;
};
矢印の右側には関数の処理を書くのですが、処理が1行で値を返す場合は波括弧とreturn
を省略して直接値を書くことが可能です。複数行の処理を書く場合は波括弧で囲み、明示的にreturn
を使います。これにより短く簡潔に関数を表現できます。
アロー関数の特徴
1. 簡潔な構文
単一式の場合:return
と{}
を省略可能
// 従来
const square = function(x) {
return x * x;
};
// アロー関数
const square = x => x * x;
引数が1つの場合:()
を省略可能
const double = x => x * 2;
2. this
の扱い
アロー関数は独自のthis
やprototype
を持たず、外側のスコープのthis
を継承します(レキシカルスコープ)。
const person = {
name: '太郎',
traditionalFunc: function() {
console.log(this.name); // '太郎'
},
arrowFunc: () => {
console.log(this.name); // undefined(外側のthisを参照)
}
};
3. コンストラクタとして使用不可
new
キーワードを使ってアロー関数を呼び出すとエラーになります。これは、アロー関数が自身のthis
やprototype
を持たず、インスタンス生成に必要な仕組みを備えていないためです。そのため、オブジェクトの生成には通常の関数(関数宣言や関数式)を使う必要があります。
const Person = (name) => {
this.name = name; // TypeError
};
// new Person('太郎'); // エラー
4. arguments
オブジェクトが無い
アロー関数には独自の arguments
オブジェクトがありません。通常の関数では関数内で渡されたすべての引数を参照できる arguments
が使えますが、アロー関数内で arguments
を使うと、外側の関数の 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 });
アロー関数の適切な使用場面
推奨するケース
- コールバック関数
コールバック関数はイベント処理や配列操作で頻繁に使われますが、アロー関数は短く書けてコードがすっきりします。特にthisの扱いで混乱しにくく、外側のスコープのthisを自動で使うため、冗長なbindや変数代入を減らせます。
const numbers = [1, 2, 3];
const doubled = numbers.map(x => x * 2);
this
のバインドが必要ない場合
アロー関数は自動的に外側のthisを参照するため、thisを新たにバインドする必要がありません。thisの値を固定したいときや、コンテキストを変えたくない場合に便利で、ミスを防ぎコードを簡潔にします。
const button = document.querySelector('button');
button.addEventListener('click', () => {
console.log('Clicked!');
});
- 簡潔な一行関数
アロー関数は式の戻り値を自動で返す短縮記法があり、一行で書けるため簡潔です。読みやすく書きやすいので、単純な処理を行う小さな関数に最適です。冗長なreturnや波括弧が不要になります。
const isEven = num => num % 2 === 0;
避けるべきケース
- メソッド定義
オブジェクトのメソッドとしてアロー関数を使うと、thisが外側のスコープを参照してしまい、そのオブジェクト自体を指さなくなります。結果としてメソッド内でオブジェクトのプロパティにアクセスできず、期待通りに動作しません。
// 👎 非推奨
const obj = {
value: 10,
getValue: () => this.value // undefined
};
// 👍 推奨
const obj = {
value: 10,
getValue() { return this.value; }
};
- コンストラクタ関数
アロー関数はnew演算子で呼び出せないため、コンストラクタ関数(インスタンスを生成する関数)として使えません。クラスや従来の関数宣言でコンストラクタを作る必要があります。
// 👎 できない
const Person = name => {
this.name = name;
};
// 👍 関数宣言を使用
function Person(name) {
this.name = name;
}
- イベントハンドラで
this
が必要な場合
イベントハンドラでthis
を使う際、アロー関数だとthis
は外側のスコープを参照し、通常のDOM要素を指しません。DOM操作で対象要素を扱いたいときは、通常関数を使うべきです。
// 👎 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
アロー関数の落とし穴
オブジェクトリテラルの返却
アロー関数でオブジェクトを直接返す場合、波括弧 {} を式として解釈されるため、単純に { key: value } と書くとブロックとみなされエラーになります。オブジェクトを返すには丸括弧で囲む必要があります。
// 👎 動かない({}がブロックと解釈される)
const createUser = (name, age) => { name, age };
// 👍 正しい書き方
const createUser = (name, age) => ({ name, age });
複数行の処理
複数行の処理を書く場合は波括弧 {}
が必要で、その中で明示的に return
を書かなければ戻り値は undefined
になります。
// 複数行の場合は明示的なreturnが必要
const process = (x, y) => {
const sum = x + y;
const product = x * y;
return { sum, product };
};
デバッグ時の匿名性
アロー関数は名前を持たない無名関数で書くことが多く、エラーメッセージやスタックトレースで関数名が表示されにくい場合があります。これにより、問題箇所の特定がやや難しくなることがあります。
// 匿名関数としてスタックトレースに表示される
const func = () => {
throw new Error('エラー発生');
};
func(); // スタックトレースで"func"ではなく"anonymous"と表示
まとめ
JavaScriptのアロー関数は、コードを短くシンプルに書けて、特にthis
の扱いが直感的になります。これにより可読性が上がり、コールバックやメソッド内でのthis
の混乱を減らせます。モダンなJavaScript開発には必須の知識です。
演習問題
初級問題(3問)
- 次の関数をアロー関数に書き換えなさい。
function multiply(a, b) {
return a * b;
}
- 次のアロー関数の呼び出し結果は?
const greet = name => `こんにちは、${name}さん!`;
console.log(greet('太郎'));
- 次のコードの間違いを修正しなさい。
const numbers = [1, 2, 3];
const squared = numbers.map(function(x) {
return x * x;
});
中級問題(6問)
- 次のアロー関数を通常の関数に書き換えなさい。
const getFullName = (firstName, lastName) => `${firstName} ${lastName}`;
- 次のオブジェクトのメソッドをアロー関数に変更した場合の問題点を指摘しなさい。
const counter = {
count: 0,
increment: function() {
this.count++;
}
};
- 次の配列から偶数のみを抽出し、それぞれを2倍した配列を作成しなさい(アロー関数を使用)。
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- 次のアロー関数を1行で書き換えなさい。
const isPositive = number => {
return number > 0;
};
- 次のコードの出力結果とその理由を説明しなさい。
const obj = {
value: 10,
traditional: function() {
console.log(this.value);
},
arrow: () => {
console.log(this.value);
}
};
obj.traditional();
obj.arrow();
- 次の高階関数を使用して、文字列を反転させる関数を作成しなさい。
const createTransformer = transform => str => transform(str);
上級問題(3問)
- カリー化された加算関数
add
をアロー関数で実装しなさい。
console.log(add(2)(3)(4)()); // 9
- 次の動作をする
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)
- アロー関数のみを使用して、次のような動作をする
createCounter
関数を実装しなさい。
javascript const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
解答例
初級問題解答
- アロー関数に書き換え
const multiply = (a, b) => a * b;
- 呼び出し結果
こんにちは、太郎さん!
const greet = name => `こんにちは、${name}さん!`;
console.log(greet('太郎')); // こんにちは、太郎さん!
- アロー関数を使用した修正
const squared = numbers.map(x => x * x);
中級問題解答
- 通常の関数に書き換え
function getFullName(firstName, lastName) {
return `${firstName} ${lastName}`;
}
- 問題点の指摘
// アロー関数にするとthisが期待通りにならない
const counter = {
count: 0,
increment: () => {
this.count++; // thisはcounterオブジェクトを指さない
}
};
- 偶数の2倍
const result = numbers
.filter(n => n % 2 === 0)
.map(n => n * 2);
- 1行で書き換え
const isPositive = number => number > 0;
- 出力結果と理由
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();
- 文字列反転関数
const reverseString = createTransformer(str =>
str.split('').reverse().join('')
);
console.log(reverseString('hello')); // 'olleh'
上級問題解答
- カリー化加算関数
const add = a => b => c => () => a + b + c;
pipe
関数
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
createCounter
関数
javascript const createCounter = () => {
let count = 0;
return () => ++count;
};