アロー関数とは、(引数) => 式 の形で書ける短い関数式で、自分専用の this・arguments を持たず、new で呼べない関数です。 書き方が短くなるだけでなく、function とは動きが5か所で異なります。この違いを知っていると、「this が undefined になった」「オブジェクトを返したはずが undefined になった」という場面で、すぐに原因へたどり着けます。

この記事では、省略記法を「書き方 → 等価な function」の対応表にまとめ、this・arguments・new・巻き上げ・メソッド定義の5項目を比較表にしたうえで、それぞれ undefined やエラーになるコードを Node.js 22.22.2 と Chromium 141 で動かした結果とともに載せています。最後に「どちらを使うか」を決める判断チャートも用意しました。コードはすべてそのまま貼って動かせます。

アロー関数の書き方の早見表

まず、書き方と等価な function 式の対応です。右の列を見れば、省略記法が何を省いているかがわかります。

やりたいこと アロー関数の書き方 等価な function 結果の例
引数0個 () => 'hi' function () { return 'hi'; } 'hi'
引数1個(括弧を省略) x => x * 2 function (x) { return x * 2; } 4 → 8
引数2個以上 (a, b) => a + b function (a, b) { return a + b; } 1, 2 → 3
デフォルト引数 (a, b = 10) => a + b function (a, b = 10) { return a + b; } 1 → 11
残余引数 (...nums) => nums.length function (...nums) { return nums.length; } 1, 2, 3 → 3
分割代入の引数 ({ name }) => name function ({ name }) { return name; } 'Sato'
式1行(return を省略) (a, b) => a + b function (a, b) { return a + b; } 3
ブロック(複数行) (a, b) => { const s = a + b; return s * 2; } function (a, b) { const s = a + b; return s * 2; } 6
オブジェクトを返す id => ({ id, done: false }) function (id) { return { id, done: false }; } { id: 7, done: false }
配列を返す () => [1, 2] function () { return [1, 2]; } [ 1, 2 ]
何もしない () => {} function () {} undefined
async async id => { ... } async function (id) { ... } Promise
関数を返す関数 x => y => x + y function (x) { return function (y) { return x + y; }; } f(1)(2) → 3
即時実行 (() => 'IIFE')() (function () { return 'IIFE'; })() 'IIFE'
async の即時実行 (async () => { ... })() (async function () { ... })() Promise

functionとの違いは次の5項目です。詳しい再現コードは後半にあります。

項目 function アロー関数
this 呼び出し方で決まる 定義した場所の this をそのまま使う
arguments 使える 持たない(残余引数 ...args を使う)
new 使える TypeError: ... is not a constructor
巻き上げ 関数宣言は定義より前で呼べる 変数のルールに従う(定義より前では呼べない)
メソッド定義 this がそのオブジェクトを指す this がオブジェクトを指さない

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「JavaScript アロー関数の書き方一覧|functionとの違い比較表」

アロー関数の基本の形

アロー関数は「関数式」の一種です。名前を付けたいときは変数に代入します。

// function 宣言
function add(a, b) {
  return a + b;
}

// function 式
const add2 = function (a, b) {
  return a + b;
};

// アロー関数
const add3 = (a, b) => a + b;

console.log(add(1, 2), add2(1, 2), add3(1, 2));
console.log(add3.name, add3.length, typeof add3);

実行結果(Node.js 22.22.2):

3 3 3
add3 2 function

typeof は 'function'、name には代入先の変数名が入ります。 つまりアロー関数も「関数」であり、呼び出し方は同じです。違いは、省略できる箇所があることと、後述の5項目だけです。

省略のルールは3つです。

省略できるもの 条件 例
function キーワード 常に(代わりに => を書く) (a, b) => a + b
引数の括弧 () 引数が「ただの名前1個」のときだけ x => x * 2
{} と return 本体が式1つのときだけ x => x * 2

引数の書き方:0個・1個・複数

引数0個は括弧が必須

const hello = () => 'hi';
console.log(hello()); // hi

括弧 () は省略できません。_ => 'hi' のように、使わない引数を1つ置く書き方もありますが、() のほうが意図が伝わります。

引数1個は括弧を省略できる

const double = x => x * 2;
const double2 = (x) => x * 2; // 括弧を付けても同じ
console.log(double(4), double2(4)); // 8 8

どちらでも動きは同じです。チームで整形ツール(Prettier など)を使うなら、その設定に合わせて統一すると読みやすくなります。

括弧が必須になる引数

引数が1個でも、次の形は括弧が必要です。

引数の形 書き方 括弧を省いた場合(Node.js 22 の出力)
2個以上 (a, b) => a + b SyntaxError: Missing initializer in const declaration
デフォルト値つき (a = 1) => a SyntaxError: Malformed arrow function parameter list
残余引数 (...a) => a SyntaxError: Unexpected token '...'
オブジェクトの分割代入 ({ name }) => name SyntaxError: Malformed arrow function parameter list
配列の分割代入 ([first]) => first SyntaxError: Malformed arrow function parameter list
const add = (a, b = 10) => a + b;
const count = (...nums) => nums.length;
const getName = ({ name }) => name;
const head = ([first]) => first;

console.log(add(1));                  // 11
console.log(count(1, 2, 3));          // 3
console.log(getName({ name: 'Sato' })); // Sato
console.log(head(['x', 'y']));        // x

迷ったら括弧を付けると覚えておけば、構文エラーになることはありません。

本体の書き方:式1行とブロック

式1行なら return を書かなくてよい

=> の右側が式1つなら、その式の値がそのまま戻り値になります。

const add = (a, b) => a + b;
console.log(add(1, 2)); // 3

ブロックにしたら return が必要

処理が複数行になるときは {} で囲みます。{} を書いたら return も自分で書きます。

const addAndDouble = (a, b) => {
  const s = a + b;
  return s * 2;
};
console.log(addAndDouble(1, 2)); // 6

{} を書いて return を書かないと、戻り値は undefined になります。

const noReturn = (a, b) => { a + b; };
console.log(noReturn(1, 2)); // undefined

map や filter の中で結果が undefined だらけになったときは、まず {} があるのに return がない形になっていないかを確認すると早く解決できます。

戻り値を捨てたいとき

逆に、式1行で書きつつ戻り値を返したくない場合は void を付けます。

const log = x => void console.log('log:', x);
console.log(log('v'));
log: v
undefined

オブジェクトを返すときは丸括弧で囲む

アロー関数でいちばんつまずきやすいのがここです。=> の直後の { は「ブロックの始まり」と解釈されるため、オブジェクトをそのまま書くと意図した値になりません。

const bad = () => { id: 1 };
const good = () => ({ id: 1 });
console.log(bad(), good());

実行結果:

undefined { id: 1 }

bad がエラーにならず undefined になるのは、{ id: 1 } が「id: というラベルが付いた、1 という文」として読まれるためです。エラーが出ないぶん気づきにくいので、形で覚えてしまうのが確実です。

プロパティが2つ以上になると、今度は構文エラーになります。

const bad2 = () => { id: 1, done: false };
SyntaxError: Unexpected token ':'

直し方は、オブジェクト全体を ( ) で囲むことです。

書き方 結果
() => { id: 1 } undefined(ラベル付きの文として解釈)
() => { id: 1, done: false } SyntaxError: Unexpected token ':'
() => ({ id: 1, done: false }) { id: 1, done: false }
() => { return { id: 1, done: false }; } { id: 1, done: false }

配列の各要素をオブジェクトに変換する場面でよく使います。

const ids = [1, 2, 3];
const tasks = ids.map(id => ({ id, done: false }));
console.log(tasks);
[
  { id: 1, done: false },
  { id: 2, done: false },
  { id: 3, done: false }
]

配列を返すときは [ がブロックと紛れないので、括弧は不要です(() => [1, 2])。

asyncアロー関数の書き方

async は引数の前に置きます。

const loadTask = async id => {
  await null; // ここに fetch などの待つ処理が入る
  return id;
};

console.log(await loadTask(5)); // 5
形 書き方
async(引数1個) async id => { ... }
async(引数0個・複数) async () => { ... } / async (a, b) => { ... }
配列の各要素を並行処理 await Promise.all(ids.map(async id => { ... }))

await の詳しい使い方やエラー処理は、async/await を扱う別の記事にゆずります。ここでは「async を先頭に付ければアロー関数でも使える」ことだけ押さえれば十分です。

即時実行(IIFE)の書き方

定義してその場で呼び出す書き方を即時実行関数式(IIFE)と呼びます。アロー関数全体を ( ) で囲み、後ろに () を付けます。

console.log((() => 'IIFE')());
console.log(await (async () => 'async IIFE')());
IIFE
async IIFE

await をトップレベルで書けない環境(CommonJS のファイルなど)では、(async () => { ... })(); で全体を包む形がよく使われます。ES モジュール(.mjs や type="module")ならトップレベルで await を書けるので、包まなくても動きます。

関数を返す関数(カリー化)の書き方

=> を続けて書くと、「関数を返す関数」になります。

const add = x => y => x + y;
const add10 = add(10);
console.log(add(1)(2), add10(5)); // 3 15

等価な function はこうなります。

const add = function (x) {
  return function (y) {
    return x + y;
  };
};

=> は右から順にまとまると読むと理解しやすくなります。x => (y => x + y) と同じ意味です。

構文エラーになる書き方と直し方

=> のまわりには、知っておくと役立つ文法の決まりが3つあります。実際のエラー文(Node.js 22.22.2)と合わせて整理します。

書き方 エラー文 直し方
引数と => の間で改行 SyntaxError: Unexpected token '=>' => の後ろで改行する
cb = cb || () => {} SyntaxError: Malformed arrow function parameter list cb = cb || (() => {})
x => { x: 1 }.x SyntaxError: Unexpected token '.' x => ({ x: 1 }).x
(a, a) => a(引数名の重複) SyntaxError: Duplicate parameter name not allowed in this context 引数名を分ける
*() => { yield 1; } SyntaxError: Unexpected token '*' ジェネレーターは function* で書く

改行の位置は次のとおりです。

// エラーになる書き方
// const f = (a, b)
//   => a + b;

// 動く書き方:=> の後ろで改行
const f = (a, b) =>
  a + b;

|| や ?? と組み合わせるときは、アロー関数を括弧で囲みます。=> はほとんどの演算子より結びつきが弱いためです。

let callback;
callback = callback || (() => {});

functionとの違い5項目の比較表

ここからが function との違いです。書き方ではなく、動きが違う点を5つにまとめます。

項目 function(宣言・式) アロー関数 困る場面 対処
this 呼び出し方で決まる(obj.f() なら obj) 持たない。定義した場所の this を使う オブジェクトのメソッドをアローで書く メソッドは name() {} で書く
arguments 渡された引数すべてが入る 持たない。外側の関数のものを見る 可変長引数を受けたい 残余引数 (...args)
new コンストラクターとして使える TypeError 部品を new で作りたい class を使う
巻き上げ 関数宣言は定義より前で呼べる const/let のルールに従う 定義より上で呼ぶ 先に定義する/関数宣言にする
メソッド定義 this がインスタンスを指す this が外側を指す prototype・getter・イベントリスナー メソッド記法/e.currentTarget

このほかに、super を自分では持たない(外側のメソッドのものを使う)、yield を使えない(ジェネレーターにできない)、call・apply・bind で this を変えられない、という違いもあります。いずれも「自分専用のものを持たない」という同じ性質から来ています。

以下、5項目を1つずつ再現します。コードは .mjs ファイル(ES モジュール)として保存し、node ファイル名.mjs で実行しています。

違い1:thisは定義した場所で決まる

オブジェクトのメソッドをアローで書くと undefined

const cart = {
  name: 'cart',
  viaFunction: function () { return this?.name; },
  viaMethod() { return this?.name; },
  viaArrow: () => this?.name,
};

console.log(cart.viaFunction()); // cart
console.log(cart.viaMethod());   // cart
console.log(cart.viaArrow());    // undefined

実行結果:

cart
cart
undefined

アロー関数の this は「呼び出したオブジェクト」ではなく、「アロー関数を書いた場所の this」です。オブジェクトリテラルの {} は関数ではないので this を作りません。そのため viaArrow の this は、その外側、つまりファイルのトップレベルの this になります。

トップレベルの this は環境によって変わります。実際に確かめた結果が次の表です。

実行環境 トップレベルの this cart.viaArrow() の結果
ES モジュール(.mjs、type="module") undefined undefined
Node.js の CommonJS(.cjs) module.exports(最初は {}) undefined({} に name がないため)
ブラウザの通常の <script>(Chromium 141) window window の name を読む(cart ではない)

どの環境でも cart は指さない、という点は共通です。オブジェクトのメソッドは viaMethod() {} の形(メソッド記法)で書くのが基本になります。

コールバックの中ではアロー関数が便利

逆に、アロー関数の this の性質が役立つのがコールバックです。

const timer = {
  label: 'timer',
  startFunction() {
    setTimeout(function () {
      console.log('function:', this?.label);
    }, 10);
  },
  startArrow() {
    setTimeout(() => {
      console.log('arrow:', this.label);
    }, 10);
  },
};

timer.startFunction();
timer.startArrow();

実行結果:

function: undefined
arrow: timer

setTimeout に渡した function は、あとで timer. を付けずに呼ばれるため、this が timer になりません(Node.js では Timeout オブジェクト、ブラウザでは window を指し、どちらも label を持たないので undefined)。アロー関数は startArrow メソッドの this をそのまま使うので、timer を指します。

「メソッドは function 系、メソッドの中のコールバックはアロー関数」という組み合わせが、this を扱ううえで最も素直な形です。

call・apply・bindでも変えられない

const other = { name: 'other' };
const arrow = () => this;
function normal() { return this?.name; }

console.log(arrow.call(other));    // undefined(ESモジュールのトップレベルの this)
console.log(arrow.bind(other)());  // undefined
console.log(normal.call(other));   // other

アロー関数の this は定義した時点で決まり、あとから差し替えられません。 call や bind に渡した第1引数は使われず、エラーにもなりません。

メソッドを変数に取り出すと this が外れる

関連して、function 側の注意点も押さえておきます。

const detached = cart.viaMethod;
console.log(detached()); // undefined

cart. を付けずに呼ぶと this は undefined(strict モード)になります。ここで ?. を付けていなければ TypeError: Cannot read properties of undefined になります。アロー関数で包む(() => cart.viaMethod())か、bind で固定すると解決できます。

違い2:argumentsを持たない

function の中では、渡された引数すべてが arguments という配列風のオブジェクトに入ります。アロー関数にはこれがありません。

function sumF() {
  return Array.from(arguments).reduce((a, b) => a + b, 0);
}
const sumA = () => arguments.length;
const sumRest = (...nums) => nums.reduce((a, b) => a + b, 0);

console.log(sumF(1, 2, 3));    // 6
console.log(sumRest(1, 2, 3)); // 6
console.log(sumA(1, 2, 3));

実行結果(ES モジュール):

6
6
ReferenceError: arguments is not defined

同じコードを Node.js の CommonJS(.cjs)で動かすと、sumA(1, 2, 3) は 5 を返しました。CommonJS ではファイル全体が1つの関数に包まれており、その関数の arguments(exports、require、module など5個)を見にいくためです。エラーにならずに別の値が返るので、原因に気づきにくい形です。

function の中に書いたアロー関数は、外側の function の arguments を使います。

function outer() {
  const inner = () => arguments[0];
  return inner('inner-arg');
}
console.log(outer('outer-arg')); // outer-arg

inner に渡した 'inner-arg' ではなく、outer に渡した 'outer-arg' が返ります。

アロー関数で可変長の引数を受けたいときは、残余引数 (...args) を使います。 こちらは本物の配列なので、map や reduce をそのまま呼べる利点もあります。

違い3:newで呼べない

function UserF(name) { this.name = name; }
const UserA = (name) => { this.name = name; };

console.log(new UserF('Sato').name);
console.log(typeof UserF.prototype, typeof UserA.prototype);
new UserA('Sato');

実行結果:

Sato
object undefined
TypeError: UserA is not a constructor

アロー関数は prototype プロパティを持たず、コンストラクターとして呼べません。 同じ形のオブジェクトをいくつも作りたいときは class を使います。

class User {
  constructor(name) { this.name = name; }
}
console.log(new User('Sato').name); // Sato

new が不要で、ただオブジェクトを組み立てて返すだけなら、アロー関数で十分です(const createUser = name => ({ name });)。

違い4:巻き上げされない

関数宣言(function 名前() {})は、ファイルや関数の先頭に持ち上げられたように扱われ、定義より上の行から呼べます。これを巻き上げ(ホイスティング)と呼びます。アロー関数は変数に代入して使うので、変数のルールに従います。

console.log(hoisted()); // ok
function hoisted() { return 'ok'; }

console.log(notYet());
const notYet = () => 'ok';

実行結果:

ok
ReferenceError: Cannot access 'notYet' before initialization

var で宣言した場合はエラー文が変わります。

console.log(varArrow());
var varArrow = () => 'ok';
TypeError: varArrow is not a function
定義の方法 定義より前で呼ぶと
function f() {}(関数宣言) 呼べる
const f = () => {} / let f = () => {} ReferenceError: Cannot access 'f' before initialization
var f = () => {} TypeError: f is not a function(変数だけ先に作られ、中身は undefined)
const f = function () {}(関数式) アロー関数と同じ(変数のルール)

巻き上げされないのは「アロー関数だから」というより「変数に代入する関数式だから」です。function 式でも同じ結果になります。

なお、エラーになるのは「定義の行が実行される前に呼んだ」ときだけです。別の関数の中から参照していて、実際に呼ばれるのが定義のあとなら動きます。

const main = () => helper(); // この時点では helper を呼んでいない
const helper = () => 'ok';
console.log(main()); // ok

ファイルの上に処理の流れ、下に補助関数を置きたいときは、関数宣言を選ぶと読みやすい順に並べられます。

違い5:メソッド定義で this が変わる場面

メソッドとして使う場面を、4つに分けて確認します。

クラスフィールドのアロー関数は this が固定される

class Counter {
  count = 0;
  incArrow = () => ++this.count;
  incMethod() { return ++this.count; }
}

const c = new Counter();
const { incArrow, incMethod } = c;

console.log(incArrow());
console.log(incMethod());

実行結果:

1
TypeError: Cannot read properties of undefined (reading 'count')

クラスフィールド(名前 = 値;)は、コンストラクターの中で実行されるのと同じ扱いです。そこで書いたアロー関数の this はインスタンスになります。そのため、変数に取り出して呼んでも this が外れません。イベントリスナーやコールバックとしてそのまま渡したいメソッドに向いています。

一方で、持ち方に違いがあります。

比べる点 incArrow = () => {}(フィールド) incMethod() {}(メソッド)
置かれる場所 インスタンスごと(Object.hasOwn(c, 'incArrow') は true) prototype に1つ(false)
インスタンス間で同じ関数か 別々(=== で false) 同じ(true)
取り出して呼ぶ this が保たれる this が undefined になる
子クラスから super.名前() で呼ぶ 呼べない(prototype にないため) 呼べる

通常はメソッド記法、コールバックとして渡すものだけアロー関数のフィールド、という分け方が扱いやすい形です。

prototypeにアロー関数を置くと undefined

function Item(name) { this.name = name; }
Item.prototype.labelArrow = () => this?.name;
Item.prototype.labelFunc = function () { return this.name; };

console.log(new Item('pen').labelArrow()); // undefined
console.log(new Item('pen').labelFunc());  // pen

オブジェクトリテラルのときと同じ理由で、アロー関数はインスタンスを指しません。

getterをアロー関数で定義すると undefined

const acc = { v: 1, get a() { return this.v; } };
Object.defineProperty(acc, 'b', { get: () => this?.v });

console.log(acc.a, acc.b); // 1 undefined

Object.defineProperty に渡す get・set も、this を使うなら function かメソッド記法で書きます。

イベントリスナーでは this が要素を指さない

Chromium 141.0.7390.37(Playwright 経由)で確認しました。

<button id="btn">保存</button>
<script>
  const btn = document.getElementById('btn');

  btn.addEventListener('click', function (e) {
    console.log('function:', this.id, this === e.currentTarget);
  });

  btn.addEventListener('click', (e) => {
    console.log('arrow:', this === window, e.currentTarget.id);
  });
</script>

ボタンをクリックしたときの出力:

function: btn true
arrow: true btn

function で書いたリスナーの this は、リスナーを登録した要素(e.currentTarget)です。アロー関数では外側の this(ここでは window)になります。アロー関数のリスナーでは this の代わりに e.currentTarget を使うと、どちらの書き方でも同じ結果になります。

superは外側のメソッドのものを使える

class Base { hi() { return 'base'; } }
class Child extends Base {
  hi() {
    const f = () => super.hi() + '+child';
    return f();
  }
}
console.log(new Child().hi()); // base+child

メソッドの中に書いたアロー関数からは、this と同じく super も使えます。メソッドではない場所(オブジェクトリテラルのプロパティに直接書いたアロー関数)で super を書くと SyntaxError: 'super' keyword unexpected here になります。

どちらを使うかの判断チャート

5つの違いをふまえた判断の流れです。上から順に当てはめてください。

flowchart TD
    A[関数を書く] --> B{new で呼ぶ?}
    B -- はい --> C[class を使う]
    B -- いいえ --> D{オブジェクトやクラスのメソッド?}
    D -- はい --> E{コールバックとして<br>取り出して渡す?}
    E -- はい --> F[クラスフィールドのアロー関数<br>name = () => {}]
    E -- いいえ --> G[メソッド記法<br>name() {}]
    D -- いいえ --> H{引数として渡す<br>コールバック?}
    H -- はい --> I[アロー関数]
    H -- いいえ --> J{定義より上で呼びたい<br>または yield を使う?}
    J -- はい --> K[function 宣言<br>ジェネレーターは function*]
    J -- いいえ --> L[アロー関数 または function 宣言<br>チームの規約に合わせる]

同じ内容を表にすると次のとおりです。

場面 選ぶ書き方 理由
map・filter・then などに渡すコールバック アロー関数 短く書け、外側の this をそのまま使える
メソッドの中の setTimeout・イベントリスナー アロー関数 メソッドの this を引き継げる
オブジェクトリテラルのメソッド メソッド記法 name() {} this がそのオブジェクトを指す
クラスのメソッド メソッド記法 name() {} prototype に1つだけ置かれ、super で呼べる
クラスのメソッドをコールバックとして渡す フィールドのアロー関数 取り出しても this が保たれる
new で作るもの class アロー関数は new できない
this に要素を受け取りたいリスナー function(または e.currentTarget) アロー関数の this は要素にならない
ジェネレーター function* アロー関数では yield を使えない
ファイルのトップレベルの関数 どちらでも可 巻き上げを使いたいなら function 宣言

トップレベルの関数をどちらで書くかは、動きの差がほとんどなく、好みと規約の領域です。1つのコードベースの中でそろっていることがいちばん読みやすさに効きます。

よく使うアロー関数のコピペ例

配列操作を中心に、そのまま使える形をまとめます。

const tasks = [
  { id: 1, title: '見積もり', done: true, minutes: 30 },
  { id: 2, title: '設計', done: false, minutes: 90 },
  { id: 3, title: 'レビュー', done: false, minutes: 45 },
];

// 変換(1行・return 省略)
const titles = tasks.map(t => t.title);

// 絞り込み
const todo = tasks.filter(t => !t.done);

// 合計
const total = tasks.reduce((sum, t) => sum + t.minutes, 0);

// 並べ替え(元の配列を変えない)
const byMinutes = tasks.toSorted((a, b) => a.minutes - b.minutes);

// 1件探す
const design = tasks.find(t => t.title === '設計');

// オブジェクトに変換(丸括弧が必要)
const options = tasks.map(t => ({ value: t.id, label: t.title }));

// 分割代入で必要な項目だけ受け取る
const labels = tasks.map(({ id, title }) => `${id}: ${title}`);

console.log(titles);
console.log(todo.length, total);
console.log(byMinutes.map(t => t.id));
console.log(design.id);
console.log(options);
console.log(labels);

実行結果(Node.js 22.22.2):

[ '見積もり', '設計', 'レビュー' ]
2 165
[ 1, 3, 2 ]
2
[
  { value: 1, label: '見積もり' },
  { value: 2, label: '設計' },
  { value: 3, label: 'レビュー' }
]
[ '1: 見積もり', '2: 設計', '3: レビュー' ]

つまずいたときのチェックリスト

症状 確認すること 直し方
戻り値が undefined {} があるのに return がない return を書く、または {} を外す
オブジェクトを返したのに undefined => { ... } になっている => ({ ... }) にする
this.xxx が undefined メソッドをアロー関数で書いている メソッド記法 name() {} にする
コールバックの中で this が変わる コールバックが function アロー関数にする
arguments is not defined アロー関数で arguments を使っている (...args) にする
is not a constructor アロー関数を new している class にする
Cannot access 'f' before initialization 定義より前で呼んでいる 定義を上に移す、または function 宣言にする
Malformed arrow function parameter list || などの後ろに括弧なしで書いている アロー関数全体を ( ) で囲む

よくある質問

Q. アロー関数と function は、結局どちらを使えばよいですか?

A. コールバックはアロー関数、オブジェクトやクラスのメソッドはメソッド記法(name() {})、new するものは class が基本です。トップレベルの関数は動きの差が小さいので、チームの規約に合わせてそろえるのがおすすめです。

Q. アロー関数でオブジェクトを返すと undefined になるのはなぜですか?

A. => の直後の { がブロックの始まりと解釈されるためです。{ id: 1 } は「id: というラベルが付いた文」として読まれ、return がないので undefined になります。() => ({ id: 1 }) のように丸括弧で囲むと、オブジェクトとして扱われます。

Q. アロー関数の this は何を指しますか?

A. アロー関数を書いた場所の this です。メソッドの中に書けばそのメソッドの this、クラスフィールドに書けばインスタンス、ファイルのトップレベルに書けば環境ごとの値(ES モジュールでは undefined、ブラウザの通常のスクリプトでは window)になります。call や bind で変えることはできません。

Q. アロー関数は function より速いですか?

A. 速度を理由に選ぶ必要はほとんどありません。選ぶ基準は this・arguments・new・巻き上げの動きの違いと、読みやすさです。なお、クラスフィールドのアロー関数はインスタンスごとに関数が作られるので、大量のインスタンスを作る場合はメソッド記法のほうがメモリの使い方が控えめになります。

まとめ

  • アロー関数は (引数) => 式 で書ける関数式。引数が名前1個なら括弧を、本体が式1つなら {} と return を省略できる
  • オブジェクトを返すときは => ({ ... }) と丸括弧で囲む。囲まないと undefined や構文エラーになる
  • this は定義した場所のものを使う。オブジェクトのメソッドには向かず、メソッドの中のコールバックに向く
  • arguments を持たないので、可変長の引数は残余引数 (...args) で受ける
  • new では呼べない(TypeError: ... is not a constructor)。インスタンスを作るなら class
  • 定義より前では呼べない(ReferenceError: Cannot access ... before initialization)。先に呼びたいなら function 宣言
  • 迷ったら「コールバックはアロー関数、メソッドはメソッド記法、new するものは class」で決める

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「JavaScript アロー関数の書き方一覧|functionとの違い比較表」

株式会社RJCでは、JavaScriptの関数の書き方と使い分けを仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?