対象読者ES6を詳しくは知らないなんとなくJavaScriptを書けるけど、JSのthisの特性についてまだよく知らないアロー関数式を知らない、または知っているけど実装経験がない概要はじめまして。@Meijin_garden)です。今回Qiita初投稿です!JavaScriptのES6で導入されたアロー関数式を、関数のただのシンタックスシュガーに過ぎないと思っていたのですが、調べてみると実際そうではないようだったので、thisの話と一緒にまとめてみました。アロー関数式とはES2015(ES6)から利用可能になった新しいJavaScriptの構文の一つです。ES6とは、2015年に標準として策定されたJavaScriptの新しい文法です。ES6では他にも、letによる変数宣言が可能になったり、promiseという非同期処理の実装ができるようになったりと、アロー関数式以外にも様々な構文追加がありました。この記事の主題はそのなかでもアロー関数なのですが、実際にES6以前の関数と、アロー関数式を利用したソースコードを比較してみるとこんな感じです。今までの関数アロー関数式の2行が出力されます。関数の中身が1文のみ(例:return文だけ)といった場合は中括弧を省略できちゃいます。console.log(y);ということで、アロー関数式を使えば、「function」を書かなくて済むため、今までより短く関数を記述することができます。アロー関数式と名前がついてはいるものの、書き方が違うだけで、挙動は今までの関数と同じように見えます。”アロー関数はthisの値を語彙的に束縛する”らしいしかし、実はアロー関数で関数を記述すると文字数が短くなるだけじゃなかったんです。MDNを見にいってみるとこのような記述がありました。短い構文を持っているのは見たらわかるけど、”thisの値を語彙的に束縛する”ってなんでしょう・・・?それを知るためには、まずはJavaScriptにおけるthisの扱いについて説明しなければなりません。一般的にJavaScriptでは、関数の中でthisを使うと、その呼び出し元のオブジェクトになります。paramとなります。printParam関数内で利用しているthis.paramの値は、呼び出し元がobjectなのかobject2なのかで異なることになります。thisの値が関数を呼び出すときに決定されていて、関数を定義した段階ではthisは何者なのか決まっていないことがわかります。誰に呼び出されるかで態度をコロコロ変えるなんて、なかなか信用出来ない奴ですね笑では、このprintParam関数を、アロー関数式を使って定義してみましょう。paramとなりました。これは、コードの最初で宣言している変数paramの値です。結論を言いますと、アロー関数式で宣言された関数は、宣言された時点で、thisを確定(=束縛)させてしまうのです。JavaScriptでvarやletを付けずに宣言された変数はグローバルオブジェクトというオブジェクトのプロパティになる。param」をconsole.logする関数だと確定するのです。呼び出し元がobjectだろうがobject2だろうが関係ありません。初心貫徹で、一貫してthisを束縛し続けるようになるのです。語彙的に束縛する、という日本語訳がちょっと微妙だとは思いますが笑、つまりアロー関数式で宣言された関数は、宣言された時点でのthisを束縛して、呼び出し元のオブジェクトにかかわらず不変のものにするということです。アロー関数式は、ただ既存の文法をより短くしたものではなく、挙動が異なるものだったのです。アロー関数式を使う場面(個人的見解)アロー関数式を使うべき場面としての個人的な見解は、ES6以前の書き方で、関数にbind(this)していた場面です。下記のようなコードを実行したい場合。}}person.callHobbyLater();person.callName();このコードは、personオブジェクトのcallNameメソッドで名前を紹介し、callHobbyLaterメソッドで趣味を話すのですが、callHobbyLaterメソッドはsetTimeout関数によって、紹介を1000ミリ秒遅らせるように設定しています。名前より前に趣味を紹介する人なんていませんからね。このコードを実行してみると、思わぬ結果となります。私の名前はmejileben趣味はundefined趣味が定義されていないことになるのです。setTimeout関数に渡された関数は、実行時の呼び出し元オブジェクトがグローバルオブジェクトになるので、personオブジェクトのhobbyが呼び出されなくなるのですね。これを防ぐためにES6以前の手法では、bind(this)を使っていました。}}person.callHobbyLater();person.callName();bind関数の引数にオブジェクトを渡すと、呼び出し元のオブジェクトをそのオブジェクトに確定できます。今回の場合、setTimeoutに渡す関数にとってのthisを、callHobbyLaterメソッドにとってのthis、つまりpersonオブジェクトに確定させておける効果を発動します。私の名前はmejileben趣味はprogrammingちゃんと自己紹介できましたね。このthisを確定させるという効果ですが、先程からお話しているアロー関数式によるthisの束縛と同じ効果を持ちます。下記のコードでも同じ動作をするということです。}}person.callHobbyLater();person.callName();ES6以前は、関数の中でthisを使う時は、本当にこいつは希望したとおりのthisなのだろうか(哲学)と考えながらコーディングし、ときにはbind(this)を付ける必要があったのですが、アロー関数になってからはその心配はなくなったということです。基本的には、ほとんどの関数はアロー関数にして問題ないと思います。使ってはいけない場面は簡単で、thisを束縛してはいけない場面です。私の名前はmejileben趣味はprogrammingが出力されます。2つの関数が見えますが、これらは両方ともthisを束縛していないからこそ正しく動いているコードです。Person関数newを付けて呼び出した時点でオブジェクトを生成し、thisをそのオブジェクトに割り当てた上で名前と趣味、doJikosyokai関数を格納して、変数mejilebenに渡している。doJikosyokai関数Personオブジェクトに格納されたときにthisが確定する(最初の例のprintParam関数に近い)。両方とも、宣言の時点でthisを確定されたら困ることがわかります。試しにアロー関数にしてみましょう。'programming');mejileben.doJikosyokai();結果、めっちゃ怒られました。(VM102:50)doJikosyokai関数をプロパティとしてセットできないと書いてあります。普通の関数式で宣言していない関数に対してプロパティをセットしようとすると怒られることがわかりました。割愛しますが、doJikosyokaiだけをアロー関数にしても変な結果になるので試してみてください。気軽にJavaScriptの実行を試すならjsFiddle3行でまとめJavaScriptのES6でアロー関数式という、今までとは違った関数の書き方が追加されたアロー関数式は既存の関数式より文字数が短くなるだけではなく、宣言時のthisを束縛して不変のものにするという効果を持っているほとんどの場面ではアロー関数式を使うほうがわかりやすくなるが、thisを束縛されて困る場面もあるので要注意!以上です。́)/JavaScriptで作っているサイトの宣伝せっかくなので自分で作ってるサイトを宣伝させてください!!この記事を書いたのがきっかけでJavaScriptにハマって、いろいろVue.jsやNuxt.jsを用いたサイト開発をしています。NoSchool僕がCTOを務めている会社です。(まだ社員2名のスタートアップです)勉強Q&Aサイトで、今まではjQueryで書かれていましたが、ALBを使うことでページごとに順番にNuxtに移行中です。よろしければどのページがNuxt移行済みか当ててみてくださいwhttps://noschool.asiaブレストLive僕が前職で開発したサイトです。オンラインでブレインストーミング(アイデア出し)ができます!Vue.js+Firebase+GCPで開発しました。Netrifyで超適当な自己紹介サイト作りました。某高専を卒業後LIFULLに入社。2019年3月からEdTechベンチャーNoSchoolのCTOに転職。WordPressからAWSへの移行を成功させ今は日々改善を進めている。upLoginユーザーは見つかりませんでした。