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を理解する - メソッド、関数、Windowの関係

Posted at

はじめに

JavaScriptを学習する上で、多くの人がつまずくのがthisの挙動です。thisの値は状況によって変わるため、予期しない動作に戸惑うことも少なくありません。

この記事では、メソッドと関数の違いから始まり、thisの決定ルール、そしてWindowオブジェクトとの関係まで、thisを理解するために必要な知識を体系的に解説します。

メソッドと関数の違い

JavaScriptにおいて、メソッドと関数は明確に区別されます。オブジェクトのキーに関数を定義した場合、それはメソッドと呼ばれます。

メソッドの定義方法

メソッドは.を使って呼び出すことができます。定義方法は2つあります。

// 方法1: functionキーワードを使う
const person = {
  name: "田中",
  greet: function() {
    console.log("こんにちは、" + this.name + "です");
  }
};

person.greet(); // "こんにちは、田中です"
// 方法2: ES6のメソッド記法(短縮記法)
const person = {
  name: "田中",
  greet() {
    console.log("こんにちは、" + this.name + "です");
  }
};

person.greet(); // "こんにちは、田中です"

どちらの方法でも同じ結果が得られますが、ES6の短縮記法の方が簡潔で読みやすいですね。

通常の関数との違い

一方、オブジェクトに属さない関数は、単に関数と呼ばれます。

function greet() {
  console.log("こんにちは");
}

greet(); // "こんにちは"

thisの基本ルール

thisの値を理解する上で最も重要なのは、thisを使っている関数がどのように呼ばれたかによってthisの値が決まるという点です。

ルール1: ドットの左側のオブジェクトがthisになる

メソッドとして呼び出された場合、.の左側にあるオブジェクトがthisとして参照されます。

const person = {
  name: "田中",
  greet() {
    console.log("こんにちは、" + this.name + "です");
  }
};

person.greet(); // "こんにちは、田中です"
// この場合、thisはpersonオブジェクトを指す

ルール2: 関数を変数に入れて呼び出すときは注意が必要

メソッドを変数に代入してから呼び出すと、thisの参照先が変わってしまいます。

const person = {
  name: "田中",
  greet() {
    console.log("こんにちは、" + this.name + "です");
  }
};

// メソッドを変数に代入
const greetFunction = person.greet;

greetFunction(); // "こんにちは、undefinedです"
// この場合、thisはWindowオブジェクトを指す

なぜこのような動作になるのでしょうか。それはWindowオブジェクトの存在が関係しています。

Windowオブジェクトとthisの関係

JavaScriptには、Windowという特別なグローバルオブジェクトが存在します。

Windowオブジェクトの特徴

JavaScriptで作成したあらゆるグローバルなオブジェクトや関数は、実はWindowオブジェクトのプロパティとして定義されています。Windowは省略することができるため、普段は見えない部分にあります。

// グローバル変数の定義
var globalName = "山田";

// 実際には以下と同じ
// window.globalName = "山田";

console.log(globalName);        // "山田"
console.log(window.globalName); // "山田"(同じ値)

thisがWindowになるケース

.の左側にオブジェクトがない状態で関数を呼び出すと、thisはWindowオブジェクトを指します。

const person = {
  name: "田中",
  greet() {
    console.log("こんにちは、" + this.name + "です");
  }
};

const greetFunction = person.greet;

// greetFunctionの呼び出しは、実は以下と同じ
// window.greetFunction();

greetFunction(); // "こんにちは、undefinedです"
// thisはWindowを指すため、window.nameを参照しようとする
// window.nameは定義されていないのでundefinedになる

よくあるthisの落とし穴と対処法

問題: コールバック関数内でのthis

メソッドをコールバック関数として渡すと、thisの参照が失われます。

const person = {
  name: "田中",
  greet() {
    console.log("こんにちは、" + this.name + "です");
  }
};

setTimeout(person.greet, 1000); // "こんにちは、undefinedです"

対処法1: アロー関数を使う

アロー関数はthisを持たず、外側のスコープのthisを継承します。

const person = {
  name: "田中",
  greet() {
    setTimeout(() => {
      console.log("こんにちは、" + this.name + "です");
    }, 1000);
  }
};

person.greet(); // 1秒後に "こんにちは、田中です"

対処法2: bindメソッドを使う

bindメソッドを使うと、thisを固定した新しい関数を作成できます。

const person = {
  name: "田中",
  greet() {
    console.log("こんにちは、" + this.name + "です");
  }
};

const boundGreet = person.greet.bind(person);
setTimeout(boundGreet, 1000); // 1秒後に "こんにちは、田中です"

thisの決定ルールまとめ

まとめ

JavaScriptのthisは、関数がどのように呼び出されたかによって値が決まります。

  • メソッドとして呼び出された場合、.の左側のオブジェクトがthisになる
  • 通常の関数として呼び出された場合、thisはWindowオブジェクトを指す
  • メソッドを変数に代入して呼び出すときは、thisの参照が変わるため注意が必要
  • Windowオブジェクトはすべてのグローバル変数や関数の親であり、通常は省略されている

thisの挙動を理解することで、予期しないバグを防ぎ、より堅牢なコードを書けるようになります。特にコールバック関数を使う場合は、アロー関数やbindメソッドを活用して、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?