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

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

More than 1 year has passed since last update.

アロー関数と関数の違い

アロー関数(arrow function)はES6から導入された「関数」の新しい書き方。

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

1. functionより短く書ける

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

// 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は実行時のレシーバであるオブジェクトになる
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();
// => 'this is within object'

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

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

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

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

a() // OK
function a() {}

arrow function は定義してから呼び出さないといけない。

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

逆に default export が1行で書けるという点では function 宣言のほうが優位になる。

default export function a() {} // OK

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

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

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

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

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のオブジェクトを結びつける。

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>
    );
  }
}

参考

freee
スモールビジネスのバックオフィス業務をテクノロジーで自動化し、日本のスモールビジネスを元気にする
http://www.freee.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
ユーザーは見つかりませんでした