【JavaScript入門】this

 JavaScript の this は、コードの書き方や呼び出し方、モードの設定などによって参照先が変化する独特なキーワードです。特に、同じ関数であっても「非厳格モードか、厳格モードか」「単体の関数か、オブジェクトのメソッドか」「thisを明示的に指定するか」によって、thisが指し示す対象が大きく異なります。ここでは、4つのファイルに分けて代表的なケースを示します。

1.非厳格モード(通常モード)の this

ファイル名: myNonStrictThisExample.html

 非厳格モード(標準モード)では、関数スコープ内での this はデフォルトでグローバルオブジェクト(ブラウザなら window)を参照します。内側の関数でも同じくグローバルオブジェクトになりやすいので注意が必要です。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>myNonStrictThisExample.html</title>
</head>
<body>
  <h1>非厳格モードでの this</h1>
  <p>開発者ツールのコンソールを開いて、出力を確認してください。</p>

  <script>
    // 非厳格モード('use strict' を記載しない)
    
    console.log('グローバル:', this); // => Window (ブラウザの場合)

    function fnc1() {
      console.log('fnc1内:', this); // => Window

      function fnc2() {
        console.log('fnc2内:', this); // => Window
      }
      fnc2();
    }

    fnc1();
  </script>
</body>
</html>

デバックコンソールの出力

グローバル: Window {window: Window, self: Window, document: #document, name: '', location: Location, …}
fnc1内: Window {window: Window, self: Window, document: #document, name: '', location: Location, …}
fnc2内: Window {window: Window, self: Window, document: #document, name: '', location: Location, …}

2.厳格モード(strict mode)の this

ファイル名: myStrictThisExample.html

 厳格モードを有効にすると、関数のスコープ内で thisundefined となります。グローバルオブジェクトを指さなくなるため、意図せずグローバルを汚染するバグを防ぐメリットがありますが、従来のコードを動かす際には注意が必要です。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>myStrictThisExample.html</title>
</head>
<body>
  <h1>厳格モードでの this</h1>
  <p>開発者ツールのコンソールを開いて、出力を確認してください。</p>

  <script>
    'use strict';

    console.log('グローバル:', this); // => Window (ここはモジュールや関数スコープ外のため)
    
    function fnc1() {
      console.log('fnc1内:', this); // => undefined (厳格モード)
      
      function fnc2() {
        console.log('fnc2内:', this); // => undefined
      }
      fnc2();
    }

    fnc1();
  </script>
</body>
</html>

デバックコンソールの出力

グローバル: Window {window: Window, self: Window, document: #document, name: '', location: Location, …}
fnc1内: undefined
fnc2内: undefined

3.メソッド呼び出し時の this

ファイル名: myMethodThisExample.html

 メソッド呼び出し(オブジェクトのプロパティが関数になっている場合)では、そのメソッド内の this は「呼び出し元のオブジェクト」を指します。ただし、内部のネストした関数をそのまま呼び出した場合は再び this が異なる対象(非厳格モードならグローバル、厳格モードなら undefined)になる点に注意が必要です。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>myMethodThisExample.html</title>
</head>
<body>
  <h1>メソッド呼び出し時の this</h1>
  <p>開発者ツールのコンソールを開いて、出力を確認してください。</p>

  <script>
    // 例: 非厳格モードでのメソッド
    const obj = {
      name: 'MyObject',
      fnc() {
        console.log('メソッド内 this:', this); // => obj を指す

        function insideFunc() {
          console.log('insideFunc 内 this:', this); 
          // => 非厳格モードでは Window、厳格モードなら undefined
        }
        insideFunc();
      }
    };

    console.log('グローバル:', this); // => Window
    obj.fnc();
  </script>
</body>
</html>

デバックコンソールの出力

グローバル: Window {window: Window, self: Window, document: #document, name: '', location: Location, …}
メソッド内 this: {name: 'MyObject', fnc: ƒ}
insideFunc 内 this: Window {window: Window, self: Window, document: #document, name: '', location: Location, …}

4.call, apply, bind で this を指定する

ファイル名: myCallApplyBindExample.html

 JavaScript の関数はオブジェクトであるため、call(), apply(), bind() というメソッドを通じて、意図的に this を設定できます。これにより、通常なら this が指せないオブジェクトを指したり、あるいは関数の this を事前に固定したりできるようになります。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>myCallApplyBindExample.html</title>
</head>
<body>
  <h1>this の指定(call/apply/bind)サンプル</h1>
  <p>開発者ツールのコンソールを開き、結果を確認してください。</p>

  <script>
    function greet(greeting, punctuation) {
      console.log(greeting, this, punctuation);
    }

    // call: 第1引数は this にする値、それ以降は普通の引数
    greet.call('HelloThis', 'おはようございます', '!');
    
    // apply: 第1引数は this にする値、第2引数は配列で、配列の要素が関数の引数として渡される
    greet.apply(['ArrayThis'], ['こんばんは', '!!']);

    // bind: this を固定した新たな関数を返す
    let greetBound = greet.bind({type: 'BoundThis'});
    greetBound('こんにちは', '〜');
  </script>
</body>
</html>

デバックコンソールの出力

おはようございます String ('HelloThis') !
こんばんは (1) ['ArrayThis'] !!
こんにちは {type: 'BoundThis'} 〜

まとめ

  • this は関数の呼び出し方や、厳格モードかどうか、またはメソッド呼び出しかなどで指す対象が変わる。
  • 非厳格モードの通常の関数では this がグローバルオブジェクト (window) を指し、厳格モードの関数は undefined
  • メソッドとしてオブジェクトのプロパティで呼ばれる場合はそのオブジェクトを指す。
  • 内部でネストされた普通の関数だと this が外とは異なる(再びグローバル or undefined)ため注意が必要。
  • call(), apply(), bind() を使うことで、任意のオブジェクトを this として強制的に関連づけできる。

こうした this の多様な挙動は、JavaScript の柔軟性であると同時に混乱の原因でもあります。コードの呼び出し方や文脈をしっかり把握して、this を正しく使いこなしましょう。