JavaScriptのthisキーワードを理解する

## はじめに

JavaScriptの世界では、「**`this`**」というキーワードがよく出てきます。しかしこの「`this`」、一体何を指すのでしょうか。初学者にとってはこの「`this`」の挙動が分かりにくく、混乱を招くこともあります。この記事では、そんな「`this`」の基本的な振る舞いとその理由を解説します。

## `this`とは何か：コンテキストという視点

「コンテキスト（context）」とは、特定のコードが実行される際の状況や背景を指します。JavaScriptでは、「`this`」はそのコードがどのようなコンテキストで実行されているかによって、指す対象が変わります。

それでは、「**`this`**」がどのように動作するか、主なコンテキストとともに見ていきましょう

1. **グローバルコンテキスト（Global Context）**：
    
    ここでは、JavaScriptのコードが全体的な範囲、すなわち全体の実行環境であるグローバルコンテキストで動作しています。
    
    たとえば、ブラウザの場合、`this`は`window`オブジェクトを指します。これはブラウザの全体的な環境を表しています。
    
    ```jsx
    console.log(this); // ブラウザでは "Window" と出力されます
    ```
    
2. **関数コンテキスト（Function Context）**：
    
    関数内での`this`は、その関数がどのように呼び出されたかによって振る舞いが変わります。
    
    例えば、オブジェクトのメソッドとして関数が呼び出された場合、`this`はそのメソッドを持つオブジェクトを指します。
    
    ```jsx
    const myObject = {
      name: 'Alice',
      greet: function() {
        console.log('Hello, ' + this.name);
      }
    }
    
    myObject.greet(); // "Hello, Alice" と出力されます
    ```
    
3. **イベントコンテキスト（Event Context）**：
イベント（例えば、ボタンのクリックなど）が発生した際の`this`は、そのイベントを発火したHTML要素を指します。これは、ユーザーの操作に反応するJavaScriptコードを書く際に特に重要です。
    
    ```jsx
    const myButton = document.querySelector('button');
    
    myButton.addEventListener('click', function() {
      console.log(this); // ここでの "this" はクリックされたボタン要素です
    });
    ```
    

## クラス内での`this`

ES6以降のJavaScriptでは、クラス内で定義されたメソッド内での`this`はそのクラスのインスタンス（つまり具体的なオブジェクト）を指します。これはオブジェクトのメソッド内での`this`と同じ振る舞いですが、クラスを使うことでより堅牢なコード設計が可能になります。

```jsx
class ExampleClass {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Hello, ${this.name}`);
  }
}

const exampleInstance = new ExampleClass('Alice');
exampleInstance.greet(); // 'Hello, Alice'

```

## コールバック関数とアロー関数

JavaScriptでは、関数を他の関数の引数として渡すことがよくあります。これをコールバック関数と呼びます。しかし、コールバック関数内で`this`を使用すると、予想外の振る舞いをすることがあります。

```jsx
const myObject = {
  name: 'Alice',
  waitAndGreet: function() {
    setTimeout(function() {
      console.log(`Hello, ${this.name}`);
    }, 1000);
  }
}

myObject.waitAndGreet(); // 'Hello, undefined'
```

ここで`setTimeout`のコールバック関数内の`this`は、`myObject`を指さずにグローバルオブジェクトを指してしまいます。これを解決する一つの方法としてアロー関数があります。アロー関数内の`this`は、その関数が定義された時点での`this`を「覚えて」います。

```jsx
const myObject = {
  name: 'Alice',
  waitAndGreet: function() {
    setTimeout(() => {
      console.log(`Hello, ${this.name}`);
    }, 1000);
  }
}

myObject.waitAndGreet(); // 'Hello, Alice'
```

このように、`this`の挙動はその使用場所や関数の種類によって変わります。`this`を使う際にはその点を意識し、必要に応じてアロー関数などを活用すると良いでしょう。

### **イベントハンドラ内での`this`**

イベントハンドラ内での「**`this`**」は、そのイベントを処理するHTML要素を指します。これは、クリックイベントやマウスオーバーイベントなどのイベントハンドラ内で特に役立ちます。

```jsx
const buttonElement = document.querySelector('button');

buttonElement.addEventListener('click', function() {
  console.log(this); // button element
});
```

### **コンストラクタとプロトタイプメソッド内での`this`**

JavaScriptのコンストラクタやプロトタイプメソッド内での「**`this`**」は、そのメソッドを呼び出したインスタンス（具体的なオブジェクト）を指します。

```jsx
function ExampleConstructor() {
  this.prop = 'Hello';
}

ExampleConstructor.prototype.method = function() {
  console.log(this.prop);
}

const exampleInstance = new ExampleConstructor();
exampleInstance.method(); // 'Hello'
```

### `call`, `apply`, `bind`での`this`

JavaScriptには「**`call`**」、「**`apply`**」、「**`bind`**」というメソッドがあり、これらは関数やメソッドの`this`を指定した値に変更することができます。

```jsx
function greet() {
  console.log(this.name);
}

const person = { name: 'Alice' };

greet.call(person); // 'Alice'
```

ここでは`greet`関数の`this`を`person`オブジェクトに変更し、その結果`'Alice'`が出力されました。

## **まとめ**

JavaScriptの`this`はその使用されるコンテキストによって指すものが変わるため、初めて学ぶ人にとっては少し難しい概念かもしれません。しかし、一つずつコンテキストを理解し、具体的なコード例を通じて学ぶことで、その振る舞いを掴むことができます。この記事が、`this`理解の一助となれば幸いです。