このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docsコミュニティーについてもっと知り、仲間になるにはこちらから。
this
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since 2015年7月.
this キーワードは、関数本体などのコードを実行するコンテキストを指します。最も一般的な用途はオブジェクトメソッドで、この場合、this はメソッドが関連付けられているオブジェクトを指し、これにより、同じメソッドをさまざまなオブジェクトで再利用することができます。
JavaScript でthis の値は、関数がどのように定義されているかではなく、どのように呼び出されるか(実行時のバインド方法)によって決まります。通常の関数がオブジェクトのメソッドとして呼び出された場合 (obj.method())、this はそのオブジェクトを指します。単独の関数として呼び出された場合(オブジェクトに関連付けられていない func())、this は通常、グローバルオブジェクト(厳格モードでない場合)、グローバルオブジェクトまたはundefined (厳格モードの場合)を指します。Function.prototype.bind() メソッドは、this のバインドが変更されない関数を作成できます。また、Function.prototype.apply() およびFunction.prototype.call() メソッドは、特定の呼び出しに対してthis の値を設定することもできます。
アロー関数では、this の扱いが異なります。定義された時点で親スコープから継承します。この動作により、アロー関数はコールバックやコンテキストの保持を行う上で特に便利です。ただし、アロー関数には独自のthis バインディングがありません。そのため、bind()、apply()、call() メソッドでthis の値を設定することはできません。また、オブジェクトメソッドで現在のオブジェクトを指すこともできません。
In this article
試してみましょう
const test = { prop: 42, func() { return this.prop; },};console.log(test.func());// 予想される結果: 42構文
this値
厳格モードでない場合は、this は常にオブジェクトを参照します。厳格モードでは、どのような値もどのような値でも取り得ます。値の決定方法に関する詳細情報は、下記を参照してください。
解説
this の値は、それが現れるコンテキスト(関数、クラス、グローバル)によって異なります。
関数コンテキスト
関数内でのthis の値は、関数の呼び出し方によって異なります。this は関数の隠し引数と考えてください。関数定義で宣言される引数と同様に、this は関数本体が評価される際に言語が自動的に作成するバインディングです。
通常の関数(アロー関数やバインド済み関数などではない)において、this の値は関数が呼び出されるオブジェクトです。言い換えれば、関数呼び出しがobj.f() の方法である場合、this はobj を参照します。例を示します。
function getThis() { return this;}const obj1 = { name: "obj1" };const obj2 = { name: "obj2" };obj1.getThis = getThis;obj2.getThis = getThis;console.log(obj1.getThis()); // { name: 'obj1', getThis: [Function: getThis] }console.log(obj2.getThis()); // { name: 'obj2', getThis: [Function: getThis] }関数は同じですが、呼び出し方法によってthis の値が異なることに注目してください。これは、関数への引数がどのように動作するのかと似ています。
this の値は、自分自身のプロパティとして機能を持つオブジェクトではなく、その機能を呼び出すために使用されるオブジェクトです。これを証明するために、プロトタイプチェーンの上位にあるオブジェクトのメソッドを呼び出してみましょう。
const obj3 = { __proto__: obj1, name: "obj3",};console.log(obj3.getThis()); // { name: 'obj3' }this の値は、関数がオブジェクトに作成時に定義された場合でも、常にその関数がどのように呼び出されたかによって変化します。
const obj4 = { name: "obj4", getThis() { return this; },};const obj5 = { name: "obj5" };obj5.getThis = obj4.getThis;console.log(obj5.getThis()); // { name: 'obj5', getThis: [Function: getThis] }メソッドにアクセスする値がプリミティブの場合、this はプリミティブ値となります。ただし、関数が厳格モードの場合のみです。
function getThisStrict() { "use strict"; // 厳格モードに入る return this;}// デモ専用のものです。組み込みのプロトタイプを変更しないでください。Number.prototype.getThisStrict = getThisStrict;console.log(typeof (1).getThisStrict()); // "number"何らかの形でアクセスされることなく関数が呼び出された場合、this はundefined となります。ただし、関数が厳格モードの場合のみです。
console.log(typeof getThisStrict()); // "undefined"厳格モードではない場合、this 置換と呼ばれる特別な処理により、この値が常にオブジェクトであることが保証されます。これはつまり、
- 関数が
thisをundefinedまたはnullに設定されて呼び出された場合、thisはglobalThisに置き換えられます。 - 関数が
thisをプリミティブ値に設定されて呼び出された場合、thisはそのプリミティブ地のラッパーオブジェクトに置き換えられます。
function getThis() { return this;}// デモ専用のものです。組み込みのプロトタイプを変更しないでください。Number.prototype.getThis = getThis;console.log(typeof (1).getThis()); // "object"console.log(getThis() === globalThis); // true一般的な関数呼び出しでは、この値は関数の接頭辞(ドットの前の部分)を通して暗黙的に引数として渡されます。また、this の値はFunction.prototype.call()、Function.prototype.apply()、Reflect.apply() のメソッドを使用して、明示的に設定することもできます。Function.prototype.bind() を使用すると、関数の呼び出し方法に関わらず変更されない特定のthis 値を持つ新しい関数を作成することができます。これらのメソッドを使用する場合、関数が厳格モードでない場合でも、上記のthis の置換ルールが適用されます。
コールバック
関数がコールバックとして渡される場合、this の値はコールバックがどのように呼び出されるかによって決まり、これはAPIの実装者によって決定されます。コールバックは通常、this の値がundefined で(オブジェクトに関連付けずに直接)呼び出されます。これは、関数が厳格モードでない場合、this の値はグローバルオブジェクト (globalThis) であることを意味します。これは、反復処理可能な配列メソッド、Promise() コンストラクターなどにも当てはまります。
function logThis() { "use strict"; console.log(this);}[1, 2, 3].forEach(logThis); // undefined, undefined, undefinedAPI によっては、コールバックの呼び出し時にthis の値を設定することができます。例えば、すべての反復処理配列メソッドと、Set.prototype.forEach() のような関連メソッドでは、オプションのthisArg 引数を受け入れます。/\
[1, 2, 3].forEach(logThis, { name: "obj" });// { name: 'obj' }, { name: 'obj' }, { name: 'obj' }時には、this 値がundefined 以外でコールバックが呼び出されることもあります。例えば、JSON.parse() のreviver 引数とJSON.stringify() のreplacer 引数はどちらも、この値が解釈/シリアライズできるプロパティが属するオブジェクトに設定されて呼び出されます。
アロー関数
アロー関数では、this 値は周囲の字句コンテキストのthis の値を保持します。言い換えれば、アロー関数の本体を評価する際、言語は新しいthis のバインドを作成しません。
例えば、グローバルコードでは、this は厳格モードであるかどうかにかかわらず、常にglobalThis となります。これは、グローバルコンテキストのバインドによるものです。
const globalObject = this;const foo = () => this;console.log(foo() === globalObject); // trueアロー関数は、その関数が存在するスコープのthis 値を囲むクロージャを作成します。つまり、アロー関数は「自動バインド」されているかのように動作します。つまり、どのように呼び出されたとしても、this は関数が作成された時点での値(例えば、グローバルオブジェクト)にバインドされます。他の関数内で作成されたアロー関数にも同じことが言えます。そのthisは、それを囲む字句コンテキストのままです。下記の例を参照してください。
さらに、call()、bind()、apply() を使用してアロー関数を呼び出す場合、thisArg 引数は無視されます。ただし、これらのメソッドを使用しても、他にも引数を渡すことができます。
const obj = { name: "obj" };// call を使用して this を設定しようとするconsole.log(foo.call(obj) === globalObject); // true// bind を使用して this を設定しようとするconst boundFoo = foo.bind(obj);console.log(boundFoo() === globalObject); // trueコンストラクター
関数がコンストラクター(new キーワード付き)として使用される場合、コンストラクター関数がどのオブジェクトにアクセスしているかに関わらず、そのthis は、構築中の新しいオブジェクトにバインドされます。コンストラクターが別のプリミティブ値以外の値を返さない限り、this の値はnew 式の値となります。
function C() { this.a = 37;}let o = new C();console.log(o.a); // 37function C2() { this.a = 37; return { a: 38 };}o = new C2();console.log(o.a); // 382 つ目の例 (C2) では、構築中にオブジェクトが返されるため、this にバインドされていた新しいオブジェクトは破棄されます。(これは本質的に、this.a = 37; の文をデッドコードにします。このコードは実行されるため、厳密にはデッドコードではありませんが、外部に影響を与えることなく削除することができます。)
super
super.method() 形式で関数が最初に呼び出された場合、method 関数内のthis はsuper.method() 呼び出しの周辺のthis 値と同じ値であり、通常super が参照するオブジェクトとは異なります。これは、super.method が上記のオブジェクトメンバーにアクセスするようなものではないためです。これは、異なるバインドルールを持つ特別な構文です。例えば、super のリファレンスを参照してください。
クラスコンテキスト
クラスは、静的コンテキストとインスタンスコンテキストの 2 つに分けることができます。コンストラクター、メソッド、インスタンスフィールド初期化子(パブリックまたはプライベート)はインスタンスコンテキストに属します。静的メソッド、静的フィールド初期化子、静的初期化ブロックは静的コンテキストに属します。それぞれのコンテキストで、this の値が異なります。
クラスのコンストラクターは常にnew で呼び出されるため、その動作は関数コンストラクターと同じです。this 値は、作成される新しいインスタンスです。 クラスメソッドは、オブジェクトリテラル内のメソッドと同じように動作します。this 値は、メソッドがアクセスされたオブジェクトです。 メソッドが他のオブジェクトに転送されない場合、this は通常、クラスのインスタンスです。
静的メソッドはthis のプロパティではありません。クラス自体のプロパティです。つまり、それらは一般的にクラスにアクセスされるため、this はクラス(またはサブクラス)の値です。静的初期化ブロックも、this を現在のクラスに設定して評価します。
フィールド初期化子もクラスのコンテキストで評価されます。インスタンスフィールドは、this を構築中のインスタンスに設定して評価されます。静的フィールドは、this を現在のクラスに設定して評価されます。これが、フィールド初期化子でアロー関数がインスタンスフィールドの場合はインスタンスに、静的フィールドの場合はクラスにバインドされる理由です。
class C { instanceField = this; static staticField = this;}const c = new C();console.log(c.instanceField === c); // trueconsole.log(C.staticField === C); // true派生クラスのコンストラクター
基本クラスのコンストラクターとは異なり、派生コンストラクターには初期のthis の結び付けがありません。super() を呼び出すとコンストラクター内にthis のバインドが作成され、基本的に以下のコードを評価する効果があります。ここで、Base は継承されたクラスです。
this = new Base();警告:this をsuper() の呼び出しの前に参照すると、エラーが発生します。
派生クラスはではsuper() を呼び出す前に return をしてはいけません。ただし、オブジェクトを返す場合やコンストラクターがない場合を除きます。
class Base {}class Good extends Base {}class AlsoGood extends Base { constructor() { return { a: 5 }; }}class Bad extends Base { constructor() {}}new Good();new AlsoGood();new Bad(); // ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructorグローバルコンテキスト
グローバル実行コンテキスト(関数やクラスの外部、グローバルスコープで定義されたブロックまたはアロー関数の内部の場合もあり)では、スクリプトが動作する実行コンテキストによってthis の値が決まります。コールバックと同様に、this の値は実行環境(呼び出し側)によって決定されます。
スクリプトの最上位レベルでは、this 値は厳格モードであるかどうかに関わらず、globalThis を参照します。これは一般的にグローバルオブジェクトと同じです。例えば、ソースが HTML の<script> 要素内に置かれ、スクリプトとして実行された場合、this === window となります。
メモ:globalThis は一般的にグローバルオブジェクトと同じ概念です(つまり、globalThis にプロパティを追加するとグローバル変数になります)。これはブラウザーとノードの場合です。しかし、ホストはグローバルオブジェクトとは関係のない値をglobalThis に指定することができます。
// ウェブブラウザーでは window オブジェクトもグローバルオブジェクトです。console.log(this === window); // truethis.b = "MDN";console.log(window.b); // "MDN"console.log(b); // "MDN"ソースがモジュールとして読み込まれた場合(HTML では、type="module" を<script> タグに追加するということ)、この場合は常に最上位でundefined となります。
ソースがeval() で実行される場合、this は直接的な eval の場合は囲んだ中のコンテキスト、間接的な eval の場合はglobalThis と同じです(別個のグローバルスクリプトで実行されているかのように)。
function test() { // 直接的な eval console.log(eval("this") === this); // 間接的な eval (厳格モード以外) console.log(eval?.("this") === globalThis); // 間接的な eval (厳格モード) console.log(eval?.("'use strict'; this") === globalThis);}test.call({ name: "obj" }); // Logs 3 "true"なお、グローバルスコープのように見えても、実行時には実際には関数にラップされているソースコードもあります。例えば、Node.js の CommonJS モジュールは関数にラップされており、this 値がmodule.exports に設定されて実行されます。イベントハンドラー属性は、この値が関連付けられている要素に設定されて実行されます。
オブジェクトリテラルではthis スコープを作成しません。オブジェクト内で定義された関数(メソッド)のみが作成されます。オブジェクトリテラルでthis を使用すると、その値は周囲のスコープから継承されます。
const obj = { a: this,};console.log(obj.a === window); // true例
>関数コンテキスト内の this
this 引数の値は、関数がどのように呼ばれるかによって決まり、定義のされ方によって決まるものではありません。
// オブジェクトを 'call' や 'apply' の最初の引数として渡すと、'this' がそれに結び付けられます。const obj = { a: "Custom" };// var で宣言された変数は、'globalThis' のプロパティになります。var a = "Global";function whatsThis() { return this.a; // 'this' の値は関数の呼び出し方によって変わります}whatsThis(); // 'Global' です。厳格モードでなければ 'this' 引数の既定値は、'globalThis'obj.whatsThis = whatsThis;obj.whatsThis(); // 'Custom' です。'this' 引数は obj に結び付けられていますcall() とapply() を使用すると、this の値を明示的な引数であるかのように渡すことができます。
function add(c, d) { return this.a + this.b + c + d;}const o = { a: 1, b: 3 };// 最初の引数は暗黙的な 'this' 引数にバインドされます。// 残りの引数は名前付き引数にバインドされます。add.call(o, 5, 7); // 16// 最初の引数は暗黙的な 'this' 引数にバインドされます。// 第 2 引数は配列であり、そのメンバーが名前付き引数にバインドされます。add.apply(o, [10, 20]); // 34this とオブジェクト変換
厳格モードでない場合、オブジェクトではないthis 値で関数が呼び出されると、this 値はオブジェクトに置き換えられます。null とundefined はglobalThis になります。7 や 'foo' などのプリミティブは、関連するコンストラクターを使用してオブジェクトに変換されます。そのため、プリミティブの数値7 はNumber ラッパークラスに変換され、文字列 'foo' はString ラッパークラスに変換されます。
function bar() { console.log(Object.prototype.toString.call(this));}bar.call(7); // [object Number]bar.call("foo"); // [object String]bar.call(undefined); // [object Window]bind() メソッド
f.bind(someObject) を呼び出すと、f と同じ本体とスコープを持つ新しい関数を生成しますが、関数がどのように呼び出されていても、this の値はbind の最初の引数に恒久的にバインドされます。
function f() { return this.a;}const g = f.bind({ a: "azerty" });console.log(g()); // azertyconst h = g.bind({ a: "yoo" }); // bind は一度しか機能しないconsole.log(h()); // azertyconst o = { a: 37, f, g, h };console.log(o.a, o.f(), o.g(), o.h()); // 37 37 azerty azertyアロー関数内の this
アロー関数は、それを包含する実行コンテキストのthis 値をクロージャとして作成します。次の例では、this の値を返す関数を返すメソッドgetThisGetter を持つobj を作成します。返される関数はアロー関数として作成されるため、そのthis は常に包含する関数のthis にバインドされます。getThisGetter 内のthis の値は、呼び出す際に設定することができ、その結果、返される関数の返値が設定されます。getThisGetter は厳格モードではない関数であると仮定します。つまり、厳格モードでないスクリプトに含まれ、クラスや厳格モードの関数にさらに入れ子にされていないということです。
const obj = { getThisGetter() { const getter = () => this; return getter; },};getThisGetter をobj のメソッドとして呼び出すことができます。これにより、本体内部でthis がobj にバインドされます。返された関数は変数fn に割り当てられます。これで、fn を呼ぶと、返されるthis の値は依然としてgetThisGetter を呼び出して設定した値、つまりobj となります。返された関数がアロー関数でなかった場合、このような呼び出しではthis の値がglobalThis となります。これは、getThisGetter が厳格モードではないためです。
const fn = obj.getThisGetter();console.log(fn() === obj); // trueしかし、obj のメソッドを呼び出さずにバインド解除すると、getThisGetter は依然としてthis の値が変化するメソッドであるため、注意が必要です。次の例でfn2()() を呼び出すと、globalThis が返されます。これは、fn2() のthis に従うことで、fn2() はオブジェクトに関連付けられることなく呼び出されるため、globalThis となるためです。
const fn2 = obj.getThisGetter;console.log(fn2()() === globalThis); // 厳格モードでなければ trueこの動作は、コールバックを定義する際にとても便利です。通常、各関数式は自分自身でthis のバインドを作成し、上位スコープのthis 値を隠してしまいます。つまり、this 値を気にしないのであれば関数をアロー関数として定義することができ、また、必要に応じて(例えばクラスメソッド内)でthis のバインドを作成することができます。setTimeout() を使用した例を参照してください。
ゲッター/セッターと this
ゲッターおよびセッターにおけるthis は、プロパティが定義されているオブジェクトではなく、プロパティにアクセスするオブジェクトに基づきます。ゲッターまたはセッターとして使用される関数は、プロパティが設定または取得されるオブジェクトにthis がバインドされています。
function sum() { return this.a + this.b + this.c;}const o = { a: 1, b: 2, c: 3, get average() { return (this.a + this.b + this.c) / 3; },};Object.defineProperty(o, "sum", { get: sum, enumerable: true, configurable: true,});console.log(o.average, o.sum); // 2 6DOM イベントハンドラー内の this
関数がイベントハンドラーとして使用された場合、そのthis はリスナーが配置されている要素に設定されます (addEventListener() 以外のメソッドで動的に追加されたリスナーについては、この規約に従わないブラウザーもあります)。
// リスナーとして呼び出された場合は、関連づけられた要素を青にするfunction bluify(e) { // 常に true console.log(this === e.currentTarget); // currentTarget と target が同じオブジェクトであれば true console.log(this === e.target); this.style.backgroundColor = "#A5D9F3";}// 文書内の各要素の一覧を取得const elements = document.getElementsByTagName("*");// クリックリスナーとして bluify を追加することで、// 要素をクリックすると青くなるようになるfor (const element of elements) { element.addEventListener("click", bluify, false);}インラインイベントハンドラー内の this
コードがインラインのイベントハンドラー属性から呼び出されたとき、そのthis にはリスナーが配置されている DOM 要素が設定されます。
<button>Show this</button>上記のアラートはbutton と表示します。ただし、外側のコードがこのように設定されたthis を持っているだけだということに注意してください。
<button> Show inner this</button>この場合、内部関数のthis 引数はglobalThis にバインドされます(すなわち、厳格モードではない場合にthis が呼び出される際に渡されない既定オブジェクト)。
クラス内のメソッドのバインド
通常の関数と同様に、メソッド内のthis の値は、どのように呼び出されるかによって異なります。クラス内のthis が常にクラスのインスタンスを参照するように、この動作をオーバーライドしておくと便利な場合もあります。これを実現するには、コンストラクターでクラスのメソッドをバインドします。
class Car { constructor() { // 違いを示すために sayHi ではなく sayBye をバインドする this.sayBye = this.sayBye.bind(this); } sayHi() { console.log(`Hello from ${this.name}`); } sayBye() { console.log(`Bye from ${this.name}`); } get name() { return "Ferrari"; }}class Bird { get name() { return "Tweety"; }}const car = new Car();const bird = new Bird();// メソッドの 'this' の値は呼び出し元に依存しますcar.sayHi(); // Hello from Ferraribird.sayHi = car.sayHi;bird.sayHi(); // Hello from Tweety// バインドされたメソッドの場合、'this' は呼び出し元に依存しませんbird.sayBye = car.sayBye;bird.sayBye(); // Bye from Ferrariメモ:クラスは常に厳格モードのコードです。これを定義せずにthis でメソッドを呼び出すとエラーが発生します。
const carSayHi = car.sayHi;carSayHi(); // TypeError because the 'sayHi' method tries to access 'this.name', but 'this' is undefined in strict mode.ただし、自動バインドされたメソッドは、クラスプロパティにアロー関数を使用することと同じ問題を抱えていることに注意してください。つまり、クラスの各インスタンスには、そのメソッドのコピーがそれぞれ保有されるため、メモリー使用量が増加します。 絶対に必要な場合のみ、これを使用してください。Intl.NumberFormat.prototype.format() の実装を模倣することもできます。プロパティをゲッターとして定義し、アクセスされた際にバインド済み関数を返し、それを保存します。これにより、関数は一度だけ作成され、必要な場合にのみ作成されます。
with 文内の this
with 文は非推奨であり、厳格モードでは利用できませんが、通常のthis バインドルールに対する例外として機能します。with 文内で関数が呼ばれ、その関数がスコープオブジェクトのプロパティである場合、this 値はobj. 接頭辞が存在するかのように、スコープオブジェクトにバインドされます。
const obj = { foo() { return this; },};with (obj) { console.log(foo() === obj); // true}仕様書
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-this-keyword> |