---
type: learn
language: javascript
slug: function/higher-order
title: "関数を値として扱う — 渡す・返す・包む"
title_tag: "JavaScript 高階関数 — 関数を渡す・返す書き方【第3回】"
summary: >
  関数は値なので、変数に入れ、配列に並べ、引数として渡せます。map に渡している形の正体、
  関数を返す関数、既存の関数を包んで機能を足す形までを実行して確かめます。
description: >
  map に渡しているものの正体は「値としての関数」です。関数を返す関数、既存の関数を包んで
  記録や再試行を足す形、呼び出しと参照を取り違える間違いまで実行して確かめられます。
status: published
difficulty: 2
minutes: 9

versions:
  verified: "Node 22.22.3"
  since: "ES5"
  deprecated: null
  removed: null

sources:
  - title: "Function Objects — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-function-objects"
  - title: "Array.prototype.map — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-array.prototype.map"
  - title: "Function.prototype.bind — MDN"
    url: "https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/bind"

terms: [高階関数, コールバック関数, 部分適用, 合成]

links:
  prev: javascript/learn/function/scope
  next: null
  related:
    - javascript/learn/array/transform
    - javascript/reference/array/map
    - javascript/why/this-binding

content_updated_at: 2026-09-08
published_at: 2026-09-08
---

**関数は値です。** 数値や文字列と同じように扱えます。

```js run
const double = (n) => n * 2;

const fns = [double, (n) => n + 1];
const obj = { run: double };

console.log(fns.map((f) => f(3)));
console.log(obj.run(5));
console.log(typeof double);
```
```output
[ 6, 4 ]
10
function
```

変数に入れ、配列に並べ、オブジェクトの値にできます。
**引数として渡すこともできます。**

## `map()` に渡しているもの

```js run
const double = (n) => n * 2;

console.log([1, 2, 3].map(double));
console.log([1, 2, 3].map((n) => n * 2));
```
```output
[ 2, 4, 6 ]
[ 2, 4, 6 ]
```

**この2つは同じことをしています。**

`map()` は「[key:配列の各要素に、渡された関数を適用する]」だけの関数です。
何をするかは、渡す側が決めます。

関数を受け取る関数、または関数を返す関数を[type:高階関数]と呼びます。
`map()` `filter()` `sort()` は全部そうです。
→ [配列を変換する・絞り込む](/ja/javascript/learn/array/transform/)

## 関数を返す

[第2回](/ja/javascript/learn/function/scope/)で見た形です。

```js run
function multiplyBy(factor) {
  return (n) => n * factor;
}

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

console.log(double(5));
console.log(triple(5));
```
```output
10
15
```

**「先に決まるもの」を固定した関数**を作れます。
これを[type:部分適用]と呼びます。

`map()` にそのまま渡せます。

```js run
function multiplyBy(factor) {
  return (n) => n * factor;
}

console.log([1, 2, 3].map(multiplyBy(10)));
```
```output
[ 10, 20, 30 ]
```

## 既存の関数を包む

**関数を受け取って、機能を足した新しい関数を返します。**

```js run
function withLog(fn, name) {
  return (...args) => {
    console.log('呼ぶ:', name, args);
    return fn(...args);
  };
}

const add = (a, b) => a + b;
const loggedAdd = withLog(add, 'add');

console.log(loggedAdd(1, 2));
```
```output
呼ぶ: add [ 1, 2 ]
3
```

**元の `add` は書き換えていません。** 包んだ新しい関数を作っただけです。

`...args` で[key:引数を全部受けて、そのまま渡して]います。
だから、どんな関数にも使えます。
→ [関数の引数 — 既定値・可変長・分割代入](/ja/javascript/reference/function/parameters/)

記録・計測・再試行・キャッシュは、この形で足せます。
→ [失敗したら再試行する](/ja/javascript/how-to/async/retry/)

## 繋げる

```js run
function twice(fn) {
  return (x) => fn(fn(x));
}

const add1 = (n) => n + 1;

console.log(twice(add1)(0));
console.log(twice(twice(add1))(0));
```
```output
2
4
```

`twice(add1)` が「2回足す関数」になり、それをさらに `twice()` に渡せます。

**関数を組み合わせて新しい関数を作れる**のが、値である利点です。

## よくある間違い

### 呼び出しと参照を取り違える

```js bad
const double = (n) => n * 2;

try {
  [1, 2, 3].map(double(0));
} catch (error) {
  console.log(error.name);
}
```
```output
TypeError
```

`double(0)` は**その場で呼んだ結果**（`0`）です。関数ではありません。
`map()` はそれを呼ぼうとして落ちます。

[dim:Node 22.22.3 の文言は「number 0 is not a function」。処理系によって変わります。]
→ [TypeError: x is not a function](/ja/javascript/errors/is-not-a-function/)

**渡すときは `()` を付けません。**

```js run
const double = (n) => n * 2;

console.log([1, 2, 3].map(double));
```
```output
[ 2, 4, 6 ]
```

### 引数が3つ渡ることを忘れる

```js bad
console.log(['1', '2', '3'].map(parseInt));
```
```output
[ 1, NaN, NaN ]
```

`map()` はコールバック関数に **`(値, 添字, 配列)` の3つ**を渡します。
`parseInt(値, 添字)` として呼ばれ、添字が[key:何進法か]の指定になってしまいます。

**関数名をそのまま渡すときは、第2・第3引数をどう扱うか確かめてください。**

```js run
console.log(['1', '2', '3'].map(Number));
console.log(['1', '2', '3'].map((s) => parseInt(s)));
```
```output
[ 1, 2, 3 ]
[ 1, 2, 3 ]
```

→ [Array.prototype.map()](/ja/javascript/reference/array/map/)

### メソッドを取り出して渡す

```js bad
const user = {
  name: 'あ',
  greet() {
    return this.name;
  },
};

const fn = user.greet;

console.log(fn());
```
```output
undefined
```

取り出した時点で `user` との繋がりが切れています。
`this` は[key:呼ばれ方]で決まるからです。

`bind()` で結んでおけば渡せます。

```js run
const user = {
  name: 'あ',
  greet() {
    return this.name;
  },
};

const fn = user.greet.bind(user);

console.log(fn());
```
```output
あ
```

→ [なぜ this は呼び方で変わるのか](/ja/javascript/why/this-binding/)

## まとめ

- 関数は**値**。変数・配列・オブジェクト・引数のどこにでも置ける
- `map()` に渡しているのは[key:値としての関数]
- 関数を返せば、**先に決まるものを固定した関数**が作れる
- 包めば、元を書き換えずに機能を足せる
- **渡すときは `()` を付けない**
- `map()` は3つの引数を渡す。`map(parseInt)` と書かない
- メソッドを取り出すと `this` が外れる。渡すなら `bind()`

## この連載はここまで

関数を作り、変数の見える範囲を知り、値として扱うところまで来ました。
ここから先は、必要になったときに引ける形でまとめてあります。

- [関数の引数 — 既定値・可変長・分割代入](/ja/javascript/reference/function/parameters/)
  … 既定値が `null` では働かない理由、`length` が数えないもの
- [なぜ this は呼び方で変わるのか](/ja/javascript/why/this-binding/)
  … アロー関数だけが例外である仕組み
- [配列を変換する・絞り込む](/ja/javascript/learn/array/transform/)
  … `map()` と `filter()` を繋げて書く
- [Promise — then / catch / finally と async / await](/ja/javascript/reference/promise/promise/)
  … 非同期の処理も、関数を渡して組み立てる
