アロー関数と関数の違いとthisの評価のされ方


## アロー関数と関数の違い
アロー関数（arrow function）はES6から導入された「関数」の新しい書き方。

ではなぜ、わざわざ新しくアロー関数が導入されたのか？
それは、違いは何かという問いと同義であり、大きく分けて理由は二つある。

**1. functionより短く書ける**

毎回`function`と宣言する必要はなく、一行で書くこともできる。

```js
// function
function inc(x) {
  return x + 1;
}

// arrow function
const inc = (x) => x + 1; // 出力の式が一行の場合はreturnは不要
```

**2. 宣言元のthisを参照する**

thisとは、オブジェクトであり、どのオブジェクトであるかは、関数の呼ばれ方によって決定する。
arrow function と function は内部のthisの参照先のオブジェクトが異なる。

- arrow function: 内部のthisは宣言時のスコープを持つオブジェクトになる
- function: 内部のthisは実行時のレシーバであるオブジェクトになる

```js
this.data = 'this is within global';

function func() {
  // 実行時のレシーバであるオブジェクトをthisとして定義する
  console.log(this.data);
}

const arrowFunc = () => {
  // 宣言時のスコープを持つオブジェクトをthisとして定義する
  // ここではグローバルオブジェクト
  console.log(this.data);
};

const f = {
  data: 'within object',
  execute: func
};
f.execute();
// => 'within object'

const af = {
  data: 'this is within object',
  execute: arrowFunc
};
af.execute();
// => 'this is within global'
```

上記の二つ以外にも差異はある。

**3. arrow functionは変数定義と同様の扱いでファイルの上の行からの解釈が明示的**

function 宣言だとこういうのが書けてしまう。

```js
a() // OK
function a() {}
```
arrow function は定義してから呼び出さないといけない。

**4. functionはdefault exportが一行で書ける**

逆に [default export が１行で書けるという点](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/export#Using_the_default_export)では function 宣言のほうが優位になる。

```js
default export function a() {} // OK

const b = () => {} 
default export b // arrow functionの場合、定義行で同時に default export できない
```

## bind(this)は何をしているのか

thisは関数の呼ばれ方によって異なるが、イベントハンドラのコールバック関数で、
`bind(this)`をするのはなぜか？

bindとは、関数内部のthisの参照するオブジェクトを確定してしまう関数のこと。

```js
this.a = 'global';
function x() { console.log(this.a) };
x();
// => 'global'
y = x.bind({ a: 'object' });
y();
// => 'object'
```

DOMが構築され、イベントによるコールバック関数が実行された時には、thisで呼び出し元のComponentのオブジェクトを参照できなる。(es6の場合)
そのために、bindを使って関数内部のthisとComponentのオブジェクトを結びつける。

```js
import React from 'react';

export default class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isToggleOn: true };
    // このオブジェクトをイベントハンドラの内部のthisに結びつける
    this._handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // `this`がこのオブジェクトであるという前提になっている
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
      <div>
        {
          /*
            bind(this)をしているので、'This'はToggle Componentになる。
            OnClickイベントはstateを変える
           */
        }
        <button onClick={this._handleClick}>
          { this.state.isToggleOn ? 'ON' : 'OFF' }
        </button>
        {
          /*
            bind(this)をしていないので、'This'はnullになる
            OnClickイベントで、以下のエラーになる。
            Uncaught TypeError: Cannot read property 'setState' of null
           */
        }
        <button onClick={this.handleClick}>
          { this.state.isToggleOn ? 'ON' : 'OFF' }
        </button>
        {
          /*
            アロー関数は、宣言時のスコープのオブジェクトになるので、'This'はToggle Componentになる
            OnClickイベントは、明示的にbind(this)をしなくても、stateを変更できる
            しかし、renderのたびに、この関数は定義される、新しい参照をもつ関数ができ、仮想DOMで差分が生じたと判断される
           */
        }
        <button onClick={() => this.handleClick()}>
          { this.state.isToggleOn ? 'ON' : 'OFF' }
        </button>
      </div>
    );
  }
}
```

### 参考
- [アロー関数 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/arrow_functions)
- [【JavaScript】アロー関数式を学ぶついでにthisも復習する話 - Qiita](https://qiita.com/mejileben/items/69e5facdb60781927929)
- [this - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/this)
- [Handling Events - React](https://reactjs.org/docs/handling-events.html)
- [Reactをes6で使う場合のbindの問題 - Qiita](https://qiita.com/cubdesign/items/ee8bff7073ebe1979936)