【CoffeeScript】 ->と=>の違い
こんにちは、マリンです。
祝!令和!!無事新しい時代が幕を開けましたね!
私も怒涛の長女卒園からの入学が終わって一安心です。
令和の時代も平和が続きますように!
そしてスキルアップできますように!!
さて、令和元年一発目の投稿は、
CoffeeScriptの=>(ファットアロー)についてです。
名前初めて知りました。。。
今までよくわからないので->こちらのみを使っていましたが、
先輩のコードを読んでいて頻繁に出てきたため勉強してみました。
ファットアローとは?
ファットアローとは、CoffeeScriptにおける関数定義の方法の一つです。
現在のthisを、定義した関数の中でも保持することができるというシロモノです。
って、なんぞや?という感じだったので詳しく調べました。
thisを保持するとは?
そもそもthis
とは、呼び出す場所や方法によってその中身が変わる特殊な変数です。
構文やオプション設定などもなく、単体でどこでも呼び出すことが可能です。
CoffeeScriptにおいては、@
で表します。
基本的には「現在のオブジェクト等」を表しており、
thisが呼び出された場所や方法によって、その「現在」が変わるため、
中身が変わってきます。
class myObj func: () -> console.log @ do -> console.log @ return myobj = new myObj myobj.func() #=> myObj {} #=> Window { postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, ...}
上記では呼び出す場所によってthis
の中身が変わっていることを検証しています。
myObjクラスの中で定義したクラスメソッドのfuncでは、
自身のクラスをthis
に格納しているようです。
しかし、そのfuncの中で呼び出している即時関数のthis
にはWindowが入っています。
「this
が保持されていない」状態ですね。
コールバック関数やイベントハンドラの中ではthis
がその対象だったりしますが、
これが保持されていない状態です。
class MyObj func: () -> console.log @ that = @ do -> console.log that return myobj = new MyObj myobj.func() #=> myObj {} #=> myObj {}
今度はfuncの中で、即時関数を実行する前に@
をthat
という変数に入れてみました。
そして即時関数ではこのthat
を出力するようにしています。
すると、実行結果がfuncと即時関数で同じになりましたね。
これが「this
を保持する」という状況です。
->と=>の違い
通常JavaScriptなどでは前述のように、
that = this
など変数に格納することによって保持するようです。
(格納する変数名はthat
もしくはself
が慣習となっています。)
このthis
を保持するための変数格納の処理を自動的に行いつつ関数宣言するのが
=>
(ファットアロー)です。
先程の例を使って->
と=>
の違いを見てみます。
class MyObj func: -> console.log @ do -> console.log @ do => console.log @ return myobj = new MyObj myobj.func() #=> myObj {} #=> Window { postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, ...} #=> myObj {}
->
(アロー?でいいのかな)の方の即時関数は、最初の例と同じように、
this
が保持されることなくWindow
が格納されています。
しかし=>
(ファットアロー)の方は、
改めて変数を定義することなくthis
が保持されていることがわかります。
これが->
と=>
の関数定義の違いです。
ちなみにこの2つがどのようにコンパイルされているか見てみましょう。
var Pages, pages; Pages = (function() { function Pages() {} Pages.prototype.func = function() { console.log(this); (function() { return console.log(this); })(); (function(_this) { return (function() { return console.log(_this); }); })(this)(); }; return Pages; })(); pages = new Pages; pages.func();
10~12行目が->
の部分、14~18行目が=>
の部分です。
ちょっと見づらいですが、=>
の方は即時関数に_this
を渡し、
それを元に無名関数を呼び出しています。
この_this
が先ほどで言うthat
の働きをしており、
即時関数の部分がthat = this
の代わりのような役割になっているようです。
即時関数の実引数にMyObjでのthis
が渡されていますね。
まとめ
->
と=>
はともにCoffeeScriptにおける関数定義の方法で、
2つの違いは、関数定義前のthis
を保持するか否か?ということでした。
先輩のコードではこの2つが入り乱れており、今まで見てみぬふりをしていましたが、
今回の大型連休のおかげで一つ謎が解けました。
ほかにも90%近く見てみぬふりをしていますが、
一つ一つ解読して私もマスターできるようになりたいです!
令和の目標はスキルアップです!!
Special thanks!!