JavaScript | アロー関数 this のレキシカル束縛

JavaScript JavaScript
スポンサーリンク

アロー関数を理解するうえで最も重要なのが this のレキシカル束縛」(=定義された場所の this をそのまま使う)です。

ここでは、
1️⃣ 通常の関数との違い
2️⃣ 図解での理解
3️⃣ 実際のコード例(動かして違いを見る)
をセットで説明します。


1️⃣ 「レキシカル束縛」とは?

レキシカル(lexical) とは「書かれた場所」という意味です。
つまり、アロー関数の this は「呼ばれた時」ではなく、「書かれた場所」で決まる ということです。

これが従来の関数との最大の違いです。


2️⃣ 図で見る this の違い

通常の関数(function)

this は「呼び出した人」によって変わります。

┌────────────────┐
│  obj                       │
│   ├─ name: "A"            │
│   └─ say: function() {    │
│        console.log(this);  │  ← 呼ばれたときに "呼び主" が this
│      }                     │
└─────┬──────────┘
           │
           ▼
呼び出し方 → obj.say();  
              ↑ここで obj が this になる

アロー関数(=>)

アロー関数は「定義されたときの外側の this」をそのまま使います。

┌────────────────┐
│  obj                       │
│   ├─ name: "A"            │
│   └─ say: () => {         │
│        console.log(this);  │  ← 外側(ここでは window / globalThis)
│      }                     │
└─────┬──────────┘
           │
           ▼
呼び出し方 → obj.say();  
              ↑ でも this は obj ではない!

🧠 つまり:

  • 通常の関数 → 呼ばれたときに「誰が呼んだか」で決まる
  • アロー関数 → 定義された場所で「すでに決まっている」

3️⃣ 実際のコードで比較

const obj = {
  name: "A",
  normal: function() {
    console.log("normal:", this.name);
  },
  arrow: () => {
    console.log("arrow:", this.name);
  }
};

obj.normal(); // normal: A
obj.arrow();  // arrow: undefined(または空文字)
JavaScript

🧩 なぜ?

  • normal呼ばれたときに obj が this になる
  • arrow定義された場所の this(ここではグローバル) を使う。
    → だから obj は参照されず、undefined になります。

4️⃣ 「定義場所の this」が効く良い例(コールバック内)

アロー関数の「this が変わらない」特性は、コールバックの中で外側の this を保ちたいときに便利です。

const counter = {
  count: 0,
  start() {
    setInterval(() => {
      // アロー関数なので this は「counter」のまま
      this.count++;
      console.log(this.count);
    }, 1000);
  }
};

counter.start();
JavaScript

🟢 この例では setInterval の中のアロー関数が
外側の this(counter) をそのまま使ってくれるので、
this.count が正しく動作します。

もしここを通常の関数で書くと、thiswindow に変わり、
this.countNaN になるか、undefined になります。


5️⃣ 図でまとめ(レキシカル束縛のイメージ)

外側のスコープ(this = counter)
│
└── setInterval( ← ここでアロー関数を定義
     │
     └── () => { console.log(this.count) }
           ↑ 「外側の this」をそのまま使う!

まとめポイント

比較項目通常の関数アロー関数
this の決まり方呼ばれたときに決まる定義されたときに決まる(外側を継承)
bind, call, apply有効効かない
コールバック内での使いやすさthis が変わって混乱しやすい外側を保持するので便利
コンストラクタに使える?✅ 使える❌ 使えない

6️⃣ ブラウザで試す用(実験HTML)

<!DOCTYPE html>
<html lang="ja">
<body>
  <button id="btn">クリック!</button>

  <script>
    const obj = {
      name: "ボタン",
      init() {
        document.getElementById("btn").addEventListener("click", function() {
          console.log("普通の関数:", this); // ← this = ボタン要素
        });

        document.getElementById("btn").addEventListener("click", () => {
          console.log("アロー関数:", this); // ← this = obj(外側の this)
        });
      }
    };
    obj.init();
  </script>
</body>
</html>
JavaScript

👀

  • 普通の関数 → this はクリックされた <button>
  • アロー関数 → this は外側(ここでは obj

See the Pen Lexical binding of this by MONO365 -Color your days- (@monoqlo365) on CodePen.

操作方法:

  • 「通常関数で実行」: obj のメソッドとして普通の関数を呼んだときの this を可視化。
  • 「アロー関数で実行」: アロー関数が定義場所の this を参照する様子を可視化。
  • 「setInterval の例」: コールバック内でアロー関数が外側の this を保持する挙動を確認。
  • 「コンソールをクリア」: ログを消します。
タイトルとURLをコピーしました