Help us understand the problem. What is going on with this article?

JavaScriptの「this」は「4種類」??

More than 3 years have passed since last update.

javascriptの「this」は「4種類」??

この記事ではベースとなる4種類の「this」を紹介します。

実際は4種類ではないのですが、
このベースの4種類を理解できれば他もすぐに理解できます。

thisの4種類のパターン

1:メソッド呼び出しパターン
2:関数呼び出しパターン
3:コンストラクタ呼び出しパターン
4:apply,call呼び出しパターン

ここで重要なのは「呼び出し元」をみることです。
なぜなら「呼び出し元」に「this」は左右されるからです。

メソッド呼び出しパターン

これはもう一番直感的にわかりやすいです。
説明はいらないんじゃないかという感じなのですが、
一応ソースを。。

メソッド呼び出しパターン
//メソッド呼び出しパターン
var myObject = {
  value: 10,
  show: function() {
    console.log(this.value);
  }
}
myObject.show(); // 10

かなり直感的ですね。
thisにはmyObjectが入っています。

関数呼び出しパターン

関数とメソッドと二つの呼び方をしてるのが、
ややこしく聞こえるかもしれません。

ただコードを見たらすぐに理解できます。

myObject.show(); // メソッド呼び出し
show(); // 関数呼び出し

「.」で呼ばれているかどうかの違いのみですね。

では関数呼び出しパターンの「this」はいかに…

関数呼び出しパターン
function show() {
  console.log(this);
  this.value = 1; // 注1
}
show(); // thisはグローバルオブジェクトをさす

この場合は「this」は「グローバルオブジェクト」を指してしまいます。
なので、注1の「value」は「グローバル変数」となります。

これを抑えておくのがポイントです。
次の例を考えてみましょう。

関数呼び出しパターン
var myObject = {
  value: 1,
  show: function() {
    console.log(this.value); // 注1

    function show() {
      console.log(this.value); // 注2
    }
    show();
  }
};
myObject.show();

ここで注1と注2の答えはわかりましたか?

注1の「this.value」は「1」
注2の「this.value」は「undefind」

注1は一つ目のメソッド呼び出しパターンですね。
注2が最初紛らわしいです。。

メソッド呼び出しの中で関数呼び出しされているので、
あくまで注2の「this」はグローバルを指してしまいます。

メソッド内で関数呼び出しになっているっていうのが落とし穴ですね。
でもこれも簡単に解決できます。

関数呼び出しパターン
var myObject = {
  value: 1,
  show: function() {
    var self = this;
    console.log(self.value); // 1

    function show() {
      console.log(self.value); // 1
    }
    show();
  }
};
myObject.show();

「this」を別の変数で持っておきます。この手法はよく使われます。
慣用的に変数は「self」, 「that」, 「_this」のどれかが使われる事が多いです。

コンストラクタ呼び出しパターン

次はコンストラクタ呼び出しパターンです。

コンストラクタ呼び出しパターン
function MyObject(value) {
  this.value = value;
  this.increment = function() {
    this.value++;
  };
}
var myObject = new MyObject(0);
console.log(myObject.value); // 0

myObject.increment();
console.log(myObject.value); // 1

これもこれだけみるとわりと直感的ですね。

「new」をつけてインスタンス生成ってことですね。
そしてその生成されるインスタンス自身が「this」にsetされます。

ただ気をつけたいのが、これはただの「関数」です。。

「new」をつけなかった場合,
MyObject(0);

これは関数呼び出しなので、
「this」はグローバルオブジェクトを指してしまいます。。

この場合はvalueとincrementは
二つともグローバル変数として定義されることになります。

コンストラクタ呼び出しを期待する場合は、
最初の文字を大きくするのが慣例ですので、この場合は「new」は必ずつけましょう!

apply, call呼び出しパターン

これは「this」を好き勝手に設定できますよっていうことです。
ライブラリとかを自作するときは非常に重宝します。

apply,call呼び出しパターン
var myObject = {
  value: 1,
  show: function() {
    console.log(this.value);
  }
};
var yourObject = {
  value: 3
};

myObject.show(); // 1

myObject.show.apply(yourObject); // 3
myObject.show.call(yourObject); // 3

「apply」と「call」を使うと「強制的にthisを束縛」できます。
「apply」と「call」の第一引数は「this」にsetしたいオブジェクトです。

あれ?…じゃあ「apply」と「call」は何が違うのかって、
それは第二引数以降の取り方が変わってきます。

apply,call呼び出しパターン
var myObject = {
  add: function(value1, value2) {
    console.log(this.value + value1 + value2);
  }
};
var yourObject = {
  value: 3
};

myObject.add.apply(yourObject, [2, 10]); // 15
myObject.add.call(yourObject, 2, 10); // 15

「apply」は第二引数に配列をとり、配列の中身が引数として渡されます。
「call」は直感的で、第二引数以降がそのまま渡されます。

二つとも第一引数は「this」で、その後の引数の取り方が違うだけです。

まとめ

「呼び出し元」に気をつけろ!
覚えるべきベースは4種類。

1:メソッド呼び出しパターン
2:関数呼び出しパターン
3:コンストラクタ呼び出しパターン
4:apply,call呼び出しパターン

てな感じです。
あっさりまとめたので、わからないところがあれば聞いてください♪

それからコンストラクタについて詳しく知りたい方はこちら
JavaScriptのクラス?コンストラクタ?

外部アカウント

技術情報のみつぶやくアカウント作成しました。JavaScriptは最新情報も追っていきます。
Twitterはこちら
Feedlyのフォローはこちら

おすすめの記事

もういい時期です。そろそろ始めましょう。ECMAScript6。
もうはじめよう、ES6~ECMAScript6の基本構文まとめ(JavaScript)

JavaScriptはオブジェクト指向?プロトタイプベースのオブジェクト指向を学ぶなら。
JavaScriptのプロトタイプからオブジェクト指向を学ぶ

JavaScriptでは関数はすべてクロージャ。
そもそもクロージャって?JavaScriptでクロージャ入門

takeharu
【名前】三上丈晴 【経歴】北海道大学理学院数学専攻を経て、2012年新卒入社。現在ピグパーティ プロダクトマネージャ 【著書】Git逆引き入門
https://twitter.com/takeharumikami
cyberagent
サイバーエージェントは「21世紀を代表する会社を創る」をビジョンに掲げ、インターネットテレビ局「AbemaTV」の運営や国内トップシェアを誇るインターネット広告事業を展開しています。インターネット産業の変化に合わせ新規事業を生み出しながら事業拡大を続けています。
http://www.cyberagent.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした