アロー関数を理解するうえで最も重要なのが 「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 が正しく動作します。
もしここを通常の関数で書くと、this は window に変わり、this.count が NaN になるか、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 を保持する挙動を確認。
- 「コンソールをクリア」: ログを消します。
