Web Marina

日々の業務や勉強などで得た知識をアウトプットしていきます。

【CoffeeScript】 ->と=>の違い

f:id:song-of-life1352607:20190505165514p:plain

こんにちは、マリンです。

祝!令和!!無事新しい時代が幕を開けましたね!

私も怒涛の長女卒園からの入学が終わって一安心です。

令和の時代も平和が続きますように!

そしてスキルアップできますように!!


さて、令和元年一発目の投稿は、

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!!

ism1000ch.hatenablog.com

umatomakun.hatenablog.com