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

#javascriptの「this」は「4種類」？？

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

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


#thisの４種類のパターン

１：メソッド呼び出しパターン
２：関数呼び出しパターン
３：コンストラクタ呼び出しパターン
４：apply,call呼び出しパターン

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



#メソッド呼び出しパターン
これはもう一番直感的にわかりやすいです。
説明はいらないんじゃないかという感じなのですが、
一応ソースを。。

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

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


#関数呼び出しパターン

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

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


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

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

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

```javascript:関数呼び出しパターン
function show() {
  console.log(this);
  this.value = 1; // 注１
}
show(); // thisはグローバルオブジェクトをさす
```
この場合は「this」は「グローバルオブジェクト」を指してしまいます。
なので、注１の「value」は「グローバル変数」となります。

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

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

ここで注１と注２の答えはわかりましたか？

注１の「this.value」は「１」
注２の「this.value」は「undefind」

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

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

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

```javascript:関数呼び出しパターン
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」のどれかが使われる事が多いです。


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

```javascript:コンストラクタ呼び出しパターン
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」を好き勝手に設定できますよっていうことです。
ライブラリとかを自作するときは非常に重宝します。

```javascript: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」は何が違うのかって、
それは第二引数以降の取り方が変わってきます。

```javascript: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」で、その後の引数の取り方が違うだけです。


#まとめ
「呼び出し元」に気をつけろ！
覚えるべきベースは４種類。

１：メソッド呼び出しパターン
２：関数呼び出しパターン
３：コンストラクタ呼び出しパターン
４：apply,call呼び出しパターン

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

それからコンストラクタについて詳しく知りたい方はこちら
[JavaScriptのクラス？コンストラクタ？](http://qiita.com/items/010752b1427773558f7c)

# 外部アカウント

技術情報のみつぶやくアカウント作成しました。JavaScriptは最新情報も追っていきます。
[Twitterはこちら]
(https://twitter.com/takeharumikami)
[Feedlyのフォローはこちら]
(http://cloud.feedly.com/#subscription%2Ffeed%2Fhttp%3A%2F%2Fqiita.com%2Ftakeharu%2Ffeed)

# おすすめの記事
もういい時期です。そろそろ始めましょう。ECMAScript6。
[もうはじめよう、ES6~ECMAScript6の基本構文まとめ(JavaScript)](http://qiita.com/takeharu/items/cbbe017bbdd120015ca0)

JavaScriptはオブジェクト指向？プロトタイプベースのオブジェクト指向を学ぶなら。
[JavaScriptのプロトタイプからオブジェクト指向を学ぶ](http://qiita.com/takeharu/items/809114f943208aaf55b3)

JavaScriptでは関数はすべてクロージャ。
[そもそもクロージャって？JavaScriptでクロージャ入門](http://qiita.com/takeharu/items/4975031faf6f7baf077a)