0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【JavaScript】this:アロー関数と通常の関数の違い

Posted at

はじめに

JavaScriptで関数を書くとき、thisの挙動に悩まされた経験はありませんか?特にアロー関数と通常の関数ではthisの決まり方が根本的に異なります。この記事では、その違いを実例を交えながら解説していきます。

通常の関数におけるthisの決定方法

通常の関数(function宣言や関数式)では、this関数が呼び出されたときの状況によって動的に決まります。

決定のタイミング

主な決定パターン

パターン1: メソッドとして呼び出し

オブジェクトのメソッドとして呼ばれた場合、thisはそのオブジェクトを指します。

const obj = {
  name: 'Taro',
  greet: function() {
    console.log(this.name);
  }
};

obj.greet(); // 'Taro' - thisはobjを指す

パターン2: 単独で呼び出し

単独で呼ばれた場合、strictモードではundefined、非strictモードではwindow(ブラウザ環境)を指します。

function showThis() {
  console.log(this);
}

showThis(); // undefined (strictモード) または window

パターン3: イベントハンドラ内

イベントハンドラでは、thisはイベントが発生した要素を指します。

button.addEventListener('click', function() {
  console.log(this); // buttonエレメントを指す
});

アロー関数におけるthisの決定方法

アロー関数のthisは、通常の関数とは全く異なる仕組みで決まります。

決定のタイミング

アロー関数では、this関数が定義された場所の外側のスコープから継承され、呼び出し方法に関わらず変わりません。これを「レキシカルなthis」と呼びます。

具体例

const obj = {
  name: 'Taro',
  greet: () => {
    console.log(this.name);
  }
};

obj.greet(); // undefined - thisはobjではなく外側のスコープを指す

この例では、アロー関数が定義された時点で外側のスコープのthis(今回だとwindowまたはundefined)を捕捉するため、obj.nameにアクセスできません。

両者の違いを比較

以下の例で、同じ状況での挙動の違いを見てみましょう。

const counter = {
  count: 0,
  
  // 通常の関数
  incrementNormal: function() {
    setTimeout(function() {
      this.count++;
      console.log(this.count); // NaN - thisがcounterを指していない
    }, 1000);
  },
  
  // アロー関数
  incrementArrow: function() {
    setTimeout(() => {
      this.count++;
      console.log(this.count); // 1 - thisがcounterを指している
    }, 1000);
  }
};

従来の回避方法

アロー関数が登場する前は、以下のような方法でthisを保持していました。

incrementOld: function() {
  const self = this; // thisを変数に保存
  setTimeout(function() {
    self.count++;
    console.log(self.count);
  }, 1000);
}

アロー関数を使えば、この手間が不要になります。

使い分けのポイント

通常の関数を使うべき場合

  • オブジェクトのメソッドとして、そのオブジェクト自身にアクセスしたい
  • イベントハンドラで、イベントが発生した要素にアクセスしたい
  • コンストラクタ関数として使いたい
const person = {
  name: 'Hanako',
  greet: function() {
    console.log(`Hello, I'm ${this.name}`);
  }
};

アロー関数を使うべき場合

  • コールバック関数内で外側のスコープのthisを使いたい
  • 短い関数を簡潔に書きたい
  • thisの値を固定したい
class Timer {
  constructor() {
    this.seconds = 0;
  }
  
  start() {
    setInterval(() => {
      this.seconds++;
      console.log(this.seconds);
    }, 1000);
  }
}

まとめ

JavaScriptのthisは、関数の種類によって決定方法が異なります。

通常の関数: 呼び出し時の状況で動的に決まる
アロー関数: 定義時の外側のスコープから継承され、固定される

この違いを理解することで、適切な関数を選択でき、this関連のバグを減らせます。特にコールバック関数やクラスのメソッド内では、アロー関数が有効ですね。状況に応じて使い分けていきましょう。​​​​​​​​​​​​​​​​

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?