JavaScriptのthisについてまとめてみた

# this　とは
JavaScript（以下JS）のコードを読んでいると、```this```がたくさん出てくることあると思います。
JSのコードで```this```が出てくると、「この```this```って何を指しているのだろうか？」と勉強したての頃はよくなりました。
```this```は日本語訳すると「これ」です。代名詞です。
JSになると「この」プロパティを指すか、「この」関数を指すか、このオブジェクトを指すか、```this```の前後によって意味が異なります。JSの始めたての人はこの`this`でつまずきやすいのでないでしょうか。しかし逆を言うとこの`this`を把握することによってコードの理解力が上がると思います。

# `this`の注意点
上記でも述べましたが、「これ」といってるだけで**呼び出した場所や方法によってその中身が変化します**。要点を抑えて正しい`this`の把握をしていきましょう。
**最初に大事なことを言う**と、thisの意味を把握するうえでの基準は`.`(**ドット**)です。

※最後の方ではドラえもんの例でごり押ししているので、ご了承ください。

# `this`の使い方
`this`の中身はいろいろ変化しますが、だいたいパターンは決まっています。次の5種類くらいです。

1. グローバルオブジェクト
2. メソッドチェーン
3. 関数呼び出し
4. コンストラクタ呼び出し
5. `call` と `apply`

以下、それぞれの種類を説明していきます。

## 1.グローバルオブジェクト
### 説明
関数の呼び出しにおいて`.`がない場合は、グローバル変数的なthisを呼びます。つまり`window`プロパティです。
### 具体例
```JavaScript
function test() {
    console.log(this);
}
test(); //.がない

//結果
//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
```
## 2. メソッドチェーン
### 説明

関数の呼び出しにおいて`.`がある場合は、その前のオブジェクトを指します。これは一般的な代名詞使用法です。以下の具体例でいうと【「この」オブジェクトの`show`関数を実行します！！】と叫んでいるのが「`myObject.show();`」です。ここではオブジェクトの`this.name`、すなわち`myObject`の`name`である`mk0812`を呼びます。ここまでの`this`記法は多分まだ簡単だと思います。

### 具体例
```JavaScript
var myObject = {
    name: 'mk0812',
    show: function(){
        console.log(this.name);
    }
}
myObject.show(); //.がある場合はその前のオブジェクトを指す

//結果
//mk0812
```

## 3.関数呼び出し
### 説明
ここから本番です。関数呼び出しとはメソッドの中で関数を呼ぶことです。言ってることがさっぱりわからないので具体例の中で説明しましょう。
### 具体例
```JavaScript
var myObject = {
    name: 'mk0812',
    show: function(){
        console.log(this.name); //①

        function show(){
            console.log(this.name); //②
        }
        show();
    }
}
myObject.show(); //.がある場合はその前のオブジェクトを指す。がメソッドの中にthisを参照する関数がある。

//結果
//①.. mk0812
//②.. undefined
```

この場合は、①は`2.メソッドチェーン`同様に`mk0812`を指しますが、②の`this`は`undefined`を指します。ここで②のthisはグローバルオブジェクトを呼び出しています。気を付けてほしいのは**メソッド内で関数呼び出しになっている場合はthisの中身は引き継がれない**ことです。そのメソッド内では`show();`と定義されています。この`show();`は誰からも定義されていないので、`.`がない関数呼び出しとしてグローバルオブジェクトを呼び出します。

`undefined`はやだ！かわいそう！というのなら、その`this`を別の変数(`self`)で置き換えて呼びましょう。

```JavaScript
var myObject = {
    name: 'mk0812',
    show: function(){
        var self = this;
        console.log(this.name); //①

        function show(){
            console.log(self.name); //②
        }
        show();
    }
}
myObject.show();

//結果
//①.. mk0812
//②.. mk0812
```

## 4.コンストラクタ呼び出し
### 説明
コンストラクタ呼び出しは、`new`をつけてインスタンスを生成します。
そのインスタンスの中身の`this`はインスタンス自身になります。

これは`new`をつけるかつけていないかでは、全然違います。
`new`をつけていない場合はただの関数です。つまり`MyObject('mk0812')`;の場合は関数呼び出しです。グローバル変数の`this`に`name`が定義されます。インスタンスとして呼びたい場合は必ず`new`をつけましょう！

### 具体例
```JavaScript
function MyObject(name){
    this.name = name;
    this.add = function(value){
        this.name = this.name + value;
    }
    this.show = function(){
        console.log(this.name);
    }
}

var mk = new MyObject('mk0812');
mk.add('aaa');
mk.show();

//結果
//mk0812aaa
```
## 5.`call` と `apply`
### 説明
`call` と `apply`は「this」を自由に操りたい場合、この方法を用いられます。最初は僕はさっぱりわかりませんでした。僕の勝手なイメージですが、この記法は自作のライブラリとかを作りたい場合、よく使われる印象があります。この「apply」と「call」を使うと「強制的にthisを束縛」できます。僕は「は？束縛？意味わからん」となりました。ここは分かりやすく「ドラえもん」で具体例を出しましょう。

### 具体例
のび太とジャイアンの関係性でいうと、のび太はジャイアンより弱い設定です（秘密道具を使うとかはなしにしましょう）。のび太が手に入れた漫画はすべてジャイアンのものになります。悲しい世界だ。。。

```JavaScript
var nobita = {
    book: 'これはのび太の漫画だよ',
    show: function() {
        console.log(this.book);
    }
};

var jian = {
    book: 'お前のものはおれのもの、おれのものはおれのもの'
}
nobita.show.apply(jian) //'お前のものはおれのもの、おれのものはおれのもの'
nobita.show.call(jian) //'お前のものはおれのもの、おれのものはおれのもの'
```
「apply」と「call」の第一引数は「this」にsetしたいオブジェクトです。のび太はジャイアンの`jian`オブジェクトに完全に支配され、bookプロパティが上書きされました。これだけ見ると「apply」と「call」の違いはあまりなさそうですが「apply」と「call」の違いは第二引数以降の取り方です。

```JavaScript
var nobita = {
    book: 'のび太の漫画だよ',
    show: function(book1,book2) {
        console.log(book1,book2 + 'は' + this.book);
    }
};

var jian = {
    book: 'おれのもの'
}
nobita.show.apply(jian,['どら焼きの本','カレーの本']); //どら焼きの本 カレーの本はおれのもの
nobita.show.call(jian,'どら焼きの本','カレーの本'); //どら焼きの本 カレーの本はおれのもの
```
「apply」は第二引数に配列をとり、配列の中身が引数として渡されます。
「call」はそのまま第二引数以降が引数として渡されます。
## その他
### bind
bindは強制的にオブジェクトと結びつける関数です。

```JavaScript
function nobita(){
    console.log(this);
}

var jian = {
    book: 'おれのもの'
}
var another_jian = nobita.bind(jian);
another_jian();

//結果
//'おれのもの'
```
関数 `another_jian` の呼び出しには `. `がついていませんが、 `bind `されているので、呼び出し時に `jian.` が付く形になります。そのため`another_jian`の`this`は`jian`（別のジャイアンもジャイアンとなる）

# まとめ
結局、`this`ってなんだっけ？ドラえもんだっけ？となった方にまとめを書きます。基本的には`.`を見て判断しましょう。使い方は次の5種類です。

1. グローバルオブジェクト .. `.`がない→グローバルオブジェクト
2. メソッドチェーン .. `.`がある→`.`の前のオブジェクトを指す。
3. 関数呼び出し .. メソッドの中の関数の`this`はグローバル
4. コンストラクタ呼び出し .. `new`をつけようね
5. `call` と `apply` .. `this`束縛マン

いろいろ、後で追記するかもしれませんが僕なりにまとめてみました。
以上、最後まで読んでいただきありがとうございました。