JavaScript | 基礎構文:スコープ・実行コンテキスト – this の基礎

JavaScript JavaScript
スポンサーリンク

this とは何か

JavaScript の this は、「今そのコードを実行している“受け手(コンテキスト)”を指す特別なキーワード」です。関数の中で this を参照すると、「誰がその関数を呼んだのか」「どんな形で呼ばれたのか」によって値が変わります。重要なのは、this は「どこで定義したか」ではなく「どう呼んだか」で決まるという点です(ただしアロー関数を除く)。


基本ルールの全体像(重要ポイントを深掘り)

this の値は、呼び出し方のパターンでほぼ決まります。直感をつかむには「呼び出し元とのつながり」を見るのがコツです。

グローバルでの this

console.log(this); // ブラウザなら window、Node.js のモジュール内トップでは {}(厳密には異なる)
JavaScript

トップレベルの this は環境によって異なります。ブラウザではほぼ window を指し、Node.js のモジュールではトップで this はモジュールスコープのオブジェクトになります。

通常の関数呼び出し

function f() {
  console.log(this);
}
f(); // 非 strict: グローバル(ブラウザなら window) / strict: undefined
JavaScript

「ただの関数」として呼ぶと、this はグローバルか undefined になります。ここが重要です:"use strict"(厳格モード)では暗黙のグローバル束縛がなくなり、thisundefined になります。

メソッド呼び出し(オブジェクト.メソッド)

const obj = {
  value: 42,
  show() {
    console.log(this.value);
  }
};
obj.show(); // 42(this は obj)
JavaScript

「オブジェクトのプロパティとしての関数」を「ドットで呼ぶ」場合、this はそのオブジェクトになります。重要:代入や参照方法を変えると this が外れることがあります(後述)。

コンストラクタ呼び出し(new)

function User(name) {
  this.name = name; // new によって「新しいインスタンス」が this
}
const u = new User("太郎");
console.log(u.name); // 太郎
JavaScript

new を付けて呼ぶと、this は新しく作られたインスタンスを指します。


呼び出し形の違いで起きる“はまりどころ”(深掘り)

呼び出し時の“受け手”が変わると this が変わります。特に「メソッドを取り外す」ケースは初心者がつまずきがちです。

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

const obj = {
  value: 100,
  show() { console.log(this.value); }
};

const fn = obj.show;
fn(); // 非 strict: undefined を参照しようとしてエラー、strict: this が undefined
JavaScript

obj.show をそのまま変数に入れて「ただの関数」として呼ぶと、this はオブジェクトを指しません。重要:関数本体は「どこで定義したか」ではなく「どう呼ばれたか」で this が決まるため、オブジェクトから切り離すと this が消えます。

call / apply / bind で this を明示的に固定する

function show() { console.log(this.msg); }
const ctx = { msg: "固定した this" };

show.call(ctx);   // 固定した this
show.apply(ctx);  // 固定した this

const bound = show.bind(ctx);
bound();          // 固定した this(常に ctx)
JavaScript
  • call/apply は「今だけ this をこれにして呼ぶ」。
  • bind は「いつ呼んでも this を固定する関数を返す」。
    「取り外したメソッドを安全に使いたい」場合は bind が便利です。

アロー関数と通常の関数の this の違い(重要ポイントを深掘り)

アロー関数は「自分専用の this を持たず、外側の this を“そのまま”使う」性質があります(レキシカル this)。これが通常の関数との決定的な違いです。

アロー関数は外側の this を捕まえる

const obj = {
  value: 7,
  showLater() {
    setTimeout(() => {
      console.log(this.value); // アロー関数は showLater の this(obj)を使う
    }, 0);
  }
};
obj.showLater(); // 7
JavaScript

通常の関数で書くと setTimeout の中は「ただの関数呼び出し」になるため、this が外れることがあります。アロー関数なら外側の this にレキシカルに束縛され、期待通りに動きます。

しかし、アロー関数を「メソッド自体」に使うのは非推奨

const obj = {
  value: 7,
  show: () => { console.log(this.value); }
};
obj.show(); // 期待通りに動かない(this は obj にならない)
JavaScript

アロー関数の this は「定義した場所の外側 this」。オブジェクトリテラルのトップで定義すると、期待する「obj」を指しません。メソッド本体は通常の関数記法で定義し、内部のコールバックにはアロー関数を使う、が定石です。


イベントハンドラと this の直感

ブラウザのイベントでは、昔ながらの DOM API では this が「イベント発生元」を指すことがありますが、近年はアロー関数や event.currentTarget を使うことが増えています。

button.addEventListener("click", function (e) {
  console.log(this === e.currentTarget); // true(function の this はイベントの受け手に結びつく)
});

button.addEventListener("click", (e) => {
  console.log(this === e.currentTarget); // false(アロー関数は外側の this)
});
JavaScript

イベントの「受け手」を使いたいなら、通常の関数記法か e.currentTarget を使うのが安全です。


strict モードと this の影響(重要ポイントを深掘り)

"use strict" を使うと、「ただの関数呼び出し」で this がグローバルに落ちず undefined になります。これにより「意図せぬグローバルを書き換える」事故を防げます。

"use strict";
function f() { console.log(this); }
f(); // undefined(安全)
JavaScript

モダンな JavaScript(ES Modules など)ではデフォルトで厳格モードに近い扱いになり、this の暗黙束縛が抑制されます。基本的には strict 前提で理解するのが良いです。


まとめと使い分けの指針

  • this は「どう呼んだか」で決まる。メソッド呼び出しならそのオブジェクト、new ならインスタンス、ただの呼び出しなら(strict で)undefined
  • メソッドを取り外すと this が失われる。bind で固定するか、呼び出し元を工夫する。
  • アロー関数は「自分の this を持たず、外側の this を使う」。メソッドの中のコールバックには便利だが、メソッド本体には通常の関数記法を使う。
  • strict モードでは「ただの関数呼び出し」で thisundefined。意図せぬグローバル事故を防げる。

まずは「メソッド・new・ただの呼び出し・アロー」の4パターンを手で動かして、this の“手触り”を覚えると、挙動が腹落ちします。

タイトルとURLをコピーしました