---
type: why
language: javascript
slug: this-binding
title: "なぜ this は呼び方で変わるのか"
title_tag: "なぜ this は呼び方で変わるのか — 決まるのは呼ぶ瞬間"
summary: >
  this は書いた場所ではなく、呼ばれ方で決まります。メソッドから取り出すと外れる理由、
  strict モードでの違い、アロー関数だけが例外である仕組みを、実行して確かめます。
description: >
  this は書いた場所ではなく呼ばれ方で決まるからです。メソッドから取り出すと外れる理由、strict モードでの違い、アロー関数だけが例外である仕組みを実行して確かめます。
status: published
difficulty: 3
minutes: 9

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

sources:
  - title: "EvaluateCall — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-evaluatecall"
  - title: "OrdinaryCallBindThis — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-ordinarycallbindthis"
  - title: "Arrow Function Definitions — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-arrow-function-definitions"

terms: [this, 呼び出し, レシーバ, 束縛]

links:
  related:
    - javascript/errors/is-not-a-function
    - javascript/errors/cannot-read-properties-of-undefined
    - javascript/reference/array/map
    - javascript/reference/promise/promise

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

**`this` は、書いた場所ではなく[key:呼ばれ方]で決まるからです。**

`obj.method()` と書けば `this` は `obj` になります。
関数を取り出して `fn()` と呼べば、`obj` はもうどこにもありません。
**関数は自分がどこに書かれていたかを覚えていません。**

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

console.log(user.greet());

const fn = user.greet;

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

**同じ関数です。** 呼び方だけを変えたら、結果が変わりました。

## 何が渡されているのか

`user.greet()` という式は、2つのことを同時にしています。

1. `user` から `greet` という関数を[fn:取り出す]
2. **`user` を `this` として渡しながら**呼ぶ

`const fn = user.greet` は[num:1]だけをします。`user` は捨てられます。
だから `fn()` には渡すものが無くなります。

| 呼び方 | `this` |
|---|---|
| `user.greet()` | `user` |
| `fn()` | [bad:無い]（下で説明） |
| `greet.call(other)` | `other` |
| `new Thing()` | 新しく作られたもの |

## 「無い」ときに何になるか

ここが分かりにくいところです。**モードによって違います。**

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

const fn = user.greet;

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

渡すものが無いと、[key:グローバルオブジェクト]が入ります。
`globalThis.name` は無いので、最初の例では `undefined` が出ていました。

`'use strict'` を付けると、代わりに `undefined` が入ります。

```js run
'use strict';

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

const fn = user.greet;

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

**こちらのほうが親切です。** 次に `this.name` を読もうとした時点で落ちるからです。

```js run
'use strict';

const counter = {
  n: 0,
  addAll(list) {
    list.forEach(function (x) {
      this.n += x;
    });

    return this.n;
  },
};

try {
  counter.addAll([1, 2]);
} catch (error) {
  console.log(error.name + ': ' + error.message);
}
```
```output
TypeError: Cannot read properties of undefined (reading 'n')
```

**`forEach()` に渡した関数は、`counter` とは無関係に呼ばれます。**
メソッドの中に書いてあっても、`this` は引き継がれません。

> `import` / `export` のあるファイル（モジュール）は、書かなくても strict モードです。
> **実務では下の例外になるほうが普通**です。

→ [Cannot read properties of undefined](/ja/javascript/errors/cannot-read-properties-of-undefined/)

## アロー関数だけが違う

アロー関数は、**自分の `this` を持ちません。**
呼ばれ方に関係なく、[key:書かれた場所]の `this` をそのまま使います。

```js run
const counter = {
  n: 0,
  addAll(list) {
    list.forEach((x) => {
      this.n += x;
    });

    return this.n;
  },
};

console.log(counter.addAll([1, 2]));
```
```output
3
```

`addAll` が `counter.addAll()` として呼ばれているので、そこでの `this` は `counter` です。
アロー関数はそれを[fn:そのまま借ります]。

**「呼び方で決まる」という規則の唯一の例外がこれです。**

### だからメソッドには使わない

```js run
const user = {
  name: 'あ',
  arrow: () => typeof this,
  method() {
    return this.name;
  },
};

console.log(user.method());
console.log(user.arrow());
```
```output
あ
object
```

`arrow` が書かれているのは[key:オブジェクトリテラルの中]で、そこはまだ `user` の中ではありません。
借りてくるのは外側の `this` です。**`user` にはなりません。**

| 使う場所 | 選ぶもの |
|---|---|
| オブジェクトのメソッド | `method() {}` |
| メソッドの中のコールバック | **アロー関数** |
| クラスのフィールドに置く関数 | アロー関数（`this` が固定される） |

## 自分で渡す

`call()` / `apply()` / `bind()` で、`this` を指定できます。

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

console.log(user.greet.call(other));
console.log(user.greet.apply(other));

const bound = user.greet.bind(other);

console.log(bound());
console.log(bound.call(user));
```
```output
い
い
い
い
```

**`bind()` で作った関数は、あとから `call()` しても変わりません。**
一度結んだら外れないので、コールバックとして渡すときに使えます。

## よくある誤解

### 「メソッドの中に書けば `this` はそのオブジェクト」

違います。**書いた場所は関係ありません。**
上の `forEach` の例がそれで、メソッドの中に書いてあっても外れます。

### 「アロー関数は `this` を親から受け取る」

正確には、[bad:受け取っていません]。**そもそも持っていない**ので、
`this` と書かれたら外側のスコープを見に行くだけです。

だから `call()` で渡しても効きません。

```js run
const arrow = () => typeof this;

console.log(arrow.call({ name: 'い' }));
```
```output
object
```

`{ name: 'い' }` は[bad:無視されました]。

### 「`this` を使わなければ安全」

そのとおりです。**渡さなくて済む形にできるなら、そのほうが単純です。**

```js run
function greet(user) {
  return user.name;
}

console.log(greet({ name: 'あ' }));
```
```output
あ
```

引数で受け取れば、呼び方に左右されません。

## 自分で確かめる

上のコードは書き換えて実行できます。次を試すと違いが見えます。

1. `'use strict'` の行を消すと、`undefined` が `globalThis` に変わる
2. `forEach((x) => ...)` を `forEach(function (x) { ... })` に戻すと落ちる
3. `bind(other)` のあとに `.call(user)` しても変わらない

## まとめ

- `this` は[key:呼ばれた瞬間]に決まる。**書いた場所は関係ない**
- `obj.method()` なら `obj`、取り出して `fn()` なら渡すものが無い
- 渡すものが無いとき、sloppy では `globalThis`、**strict では `undefined`**
- アロー関数は `this` を持たない。**外側のものをそのまま使う**
- メソッドはふつうの書き方、その中のコールバックはアロー関数

コールバックにアロー関数を渡す形は、非同期処理をまとめて走らせるときにもよく出ます。
→ [複数の非同期処理を同時に走らせる](/ja/javascript/how-to/async/parallel/)
