このキーワード

キーワード this は、呼び出し時に関数にバインドされているオブジェクトの値を参照します。つまり、関数がメソッドとして呼び出されるか、スタンドアロン関数として呼び出されるか、コンストラクタとして呼び出されるかによって、値が異なります。

関数が呼び出されると、その関数を含むオブジェクトへの参照としてバックグラウンドでキーワード this のインスタンスが作成され、スコープ内から関数とともに定義されているプロパティとメソッドにアクセスできるようになります。this の操作は、const で宣言された変数の操作といくつかの点で類似しています。定数と同様に、this は削除できず、値の再割り当てもできませんが、this キーワードに含まれるオブジェクトのメソッドとプロパティは変更できます。

グローバル バインディング

関数またはオブジェクトのコンテキストの外部で、thisglobalThis プロパティを参照します。これは、ほとんどの JavaScript 環境でグローバル オブジェクトへの参照です。ウェブブラウザで実行されるスクリプトのコンテキストでは、グローバル オブジェクトは window オブジェクトです。

this;
> Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, ...}

Node.js では、globalThisglobal オブジェクトです。

$ node
Welcome to Node.js v20.10.0.
Type ".help" for more information.
> this
<ref *1> Object [global] {
...
}

厳格モードの外部では、this はスタンドアロン関数内のグローバル オブジェクトも参照します。これは、親 Window がこれらの関数を効果的に「所有」しているオブジェクトであるためです。

function myFunction() {
    console.log( this );
}
myFunction();
> Window {...}

(function() {
    console.log( this );
}());
> Window {...}

strict モードを使用する場合、スタンドアロン関数内の this の値は undefined になります。

(function() {
    "use strict";
    console.log( this );
}());
> undefined

厳格モードを導入する前は、thisnull または undefined の値は、グローバル オブジェクトへの参照に置き換えていました。この従来の動作のため、グローバル バインディングが「デフォルト バインディング」と呼ばれることがあります。

暗黙的バインディング

関数がオブジェクトのメソッドとして呼び出されると、そのメソッド内の this のインスタンスが、メソッドを含むオブジェクトを参照し、関連するメソッドとプロパティにアクセスできるようになります。

let myObject = {
    myValue: "This is my string.",
    myMethod() {
            console.log( this.myValue );
    }
};

myObject.myMethod();
> "This is my string."

this の値は、関数とその包含オブジェクトの定義方法によって異なります。this の値のコンテキストは、現在の実行コンテキストです。この場合、実行コンテキストは myObject オブジェクトが myMethod メソッドを呼び出すことになるため、myObjectthis の値です。上記の例では専門用語に思えるかもしれませんが、this の高度な使い方の場合は、この点に注意する必要があります。

一般に、this は、周囲のコードが特定の構造を持つことを想定していない方法で使用します。このルールの例外は、ES5 のアロー関数です。

アロー関数の this

arrow 関数では、this語彙を含む環境のバインディングに解決されます。つまり、アロー関数の this は、その関数に最も近いコンテキストの this の値を参照します。

let myObject = {
    myMethod() { console.log( this ); },
    myArrowFunction: () => console.log( this ),
    myEnclosingMethod: function () {
        this.myArrowFunction = () => { console.log(this) };
    }
};

myObject.myMethod();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }

myObject.myArrowFunction();
> Window {...}

上記の例では、myObject.myMethod() は、そのメソッドを「所有」するオブジェクトとして myObject をログに記録しますが、myObject.myArrowFunction()globalThis(または undefined)を返します。これは、アロー関数内の this のインスタンスが、代わりに最も包含するスコープを参照しているためです。

次の例では、myEnclosingMethod の実行時に、それを含むオブジェクトにアロー関数が作成されます。アロー関数内の this のインスタンスは、アロー関数を含むメソッドである包含環境内の this の値を参照するようになりました。myEnclosingMethod 内の this の値は myObject を参照するため、アロー関数を定義した後は、アロー関数内の thismyObject を参照します。

let myObject = {
    myMethod() { console.log( this ); },
    myEnclosingMethod: function () {
        this.myArrowFunction = () => { console.log(this) };
    }
};

myObject.myEnclosingMethod();
myObject.myArrowFunction();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }

明示的バインディング

暗黙的バインディングは、this を使用する際のほとんどのユースケースに対応します。ただし、想定されるコンテキストではなく、特定の実行コンテキストを表すために、this の値が必要になる場合があります。例として、少し古いものとして、setTimeout のコールバック関数内で this を操作する例を示します。このコールバックには独自の実行コンテキストがあるためです。

var myObject = {
  myString: "This is my string.",
  myMethod() {
    console.log( this.myString );
  }
};
myObject.myMethod();
> "This is my string."

setTimeout( myObject.myMethod, 100 );
> undefined

setTimeout のこの特定の欠点は他の機能で対処されていますが、this が「失われる」という同様の問題は、以前に目的のコンテキストの範囲内で this の値への明示的な参照を作成することで対処されています。以前のコードベースでは、thatself_this などの識別子を使用して変数に this のインスタンスが割り当てられる場合があります。これらは、渡された this 値を含む変数の一般的な識別子規則です。

call()bind()、または apply() メソッドを使用して関数を呼び出すと、this は呼び出されるオブジェクトを明示的に参照します。

let myFunction = function() {
    console.log( this.myValue );
}

let myObject = {
   "myValue" : "This is my string."
 };

myFunction.call( myObject );
> "This is my string."
var myObject = {
  myString: "This is my string.",
  myMethod() {
    console.log( this.myString );
  }
};

setTimeout( myObject.myMethod.bind( myObject ), 100 );
> "This is my string."

明示的バインディングは、暗黙的バインディングによって提供される this 値をオーバーライドします。

let myObject = {
    "myValue" : "This string sits alongside myMethod.",
    myMethod() {
        console.log( this.myValue );
    }
};
let myOtherObject = {
    "myValue" : "This is a string in another object entirely.",
};

myObject.myMethod.call( myOtherObject );
> "This is a string in another object entirely."

関数が this の値を undefined または null に設定する方法で呼び出された場合、厳格モード以外では、その値は globalThis に置き換えられます。

let myFunction = function() {
    console.log( this );
}

myFunction.call( null );
> Window {...}

同様に、関数が this にプリミティブ値を与える方法で呼び出された場合、その値は、厳格モードの外でプリミティブ値のラッパー オブジェクトに置き換えられます。

let myFunction = function() {
    console.log( this );
}

let myNumber = 10;

myFunction.call( myNumber );
> Number { 10 }

strict モードでは、渡された this 値はプリミティブ値、null 値、undefined 値であっても、オブジェクトに強制変換されません。

"use strict";
let myFunction = function() {
    console.log( this );
}

let myNumber = 10;

myFunction.call( myNumber );
> 10

myFunction.call( null );
> null

new バインディング

new キーワードを使用してクラスをコンストラクタとして使用する場合、this は新しく作成されたインスタンスを参照します。

class MyClass {
    myString;
    constructor() {
        this.myString = "My string.";
    }
    logThis() {
        console.log( this );
    }
}
const thisClass = new MyClass();

thisClass.logThis();
> Object { myString: "My string." }

同様に、new を使用して呼び出されるコンストラクタ関数内の this の値は、作成されるオブジェクトを参照します。

function MyFunction() {
  this.myString = "My string.";
  this.logThis = function() {
    console.log( this );
  }
}
const myObject = new MyFunction();

myObject.logThis();
> Object { myString: "My string.", logThis: logThis() }

イベント ハンドラのバインディング

イベント ハンドラのコンテキストでは、this の値はそれを呼び出すオブジェクトを参照します。つまり、イベント ハンドラのコールバック関数内では、this がハンドラに関連付けられた要素を参照します。

let button = document.querySelector( "button" );

button.addEventListener( "click", function( event ) { console.log( this ); } );

ユーザーが前のスニペットで button を操作すると、結果は <button> 自体を含む要素オブジェクトになります。

> Button {}

アロー関数がイベント リスナー コールバックとして使用される場合、this の値は、最も近い実行コンテキストから再び提供されます。つまり、トップレベルでは、イベント ハンドラ コールバック関数内の thisglobalThis(厳格モードでは undefined)です。

let button = document.querySelector( "button" );

button.addEventListener( "click", ( event ) => { console.log( this ); } );
> undefined

他のオブジェクトと同様に、call()bind()、または apply() メソッドを使用してイベント リスナーのコールバック関数を参照すると、this はオブジェクトを明示的に参照します。

let button = document.querySelector( "button" );
let myObject = {
    "myValue" : true
};
function handleClick() {
    console.log( this );
}

button.addEventListener( "click", handleClick.bind( myObject ) );
> Object { myValue: true }

理解度をチェックする

ウェブブラウザで実行されるスクリプトの場合、this が関数またはオブジェクトのコンテキストの外部で使用されるときに参照されるグローバル オブジェクトは何ですか。

window オブジェクト
browser オブジェクト
undefined オブジェクト