UXPに備えてモダンなJSの書き方に慣れる(アロー関数)
PhotoshopにUXPがついに来ましたが今後ECMA3ベースのjsxからUXPに移行するにあたり最新のjsの書き方がAdobe scriptを書く上でスタンダードになると思います。しかし今まで古い書き方に慣れていたのにいきなり新しい書き方に慣れようにも移行しづらいと思います。実際ECMA3からECMA2015の進化は飛躍的な進化でしたしその後のECMA2016,ECMA2017と年々さらに進化しています。もしくはECMA2015の進化影に隠れがちですがその前にECMA5の進化もありました。Adobe jsxはこのECMA5すらもサポートしていません。それくらいECMA3は古いです。今websiteで一番対応がネックとなっているブラウザー、internet explorer11でさえもECMA5には対応しています。(ECMA2015に関してはほとんど未対応)話がずれましたが来るべきUXP(といってもCEPでパネル上ではバリバリ使えましたが)に備えて新しい書き方を解説。今回その中でも見た目が???なものをとりあげます。
アロー関数
functionと似たような役割を持つのがこのアロー関数です。ほとんど役割は同じですが全く同じわけではありません。functionの書き方を省略するだけが役割ではないので注意。結構前からQiitaの記事でもアロー関数を使ったコードを見るようになりましたが一見すると???なコードが多いのが特徴です。まずはアロー関数と通常の関数の基本の違い以下簡単なコード。
ただし通常の関数はコードが実行される前に読み上げられるので宣言の前に実行しても正常に実行されます。それに対してこの形のアロー関数はconstで宣言されているので宣言前に実行するとエラーになります。
ただしfunctionからコンストラクトを作成するようなconst等の宣言を必要とする場合は宣言後に実行しないとエラーになります。
returnの省略
アロー関数は一行でまとめる場合returnを省略できます。
初見だとこの辺で混乱すると思います。アロー関数は一行でまとめる場合関数内の値をそのままreturnで返します。さらに関数スコープを囲む{}まで省略されます。なので->矢印以降は関数の中身のみ残るので見た目はかなり簡素に、しかし慣れてない人にとっては不思議なコードになります。さらに引数も渡される値が一つの場合は()まで省略されます。別に個人で開発する場合はこういう書き方に慣れなくても問題はないですがgoogleでjsのコードを検索するとこういった書き方が何百を出てくるので読めるようにしておいた方がいいとは思います。ちなみにオブジェクトを返す場合オブジェクトの{}が関数スコープを表す{}と被ってエラーになる場合があるのでオブジェクトを返すアロー関数を書く場合は()で囲ってください。
ちなみにカリー化は以下の通り。
この書き方はECMA5より追加されたmapやreduce等のarrayメソッドとよく使われます。
これらのarrayメソッドについては今回説明は省きますがアロー関数と組み合わせることでfor文で行っていた大部分の処理をわずか一行のコードで済ませてしますことが可能です。
thisの挙動が異なる
通常オブジェクトの関数内でのthisは呼び出しもとのオブジェクトそのものを示します。例えば以下。
obj.funcメソッドの場合予想通りobjのプロパティのx,10を返しました。しかしarrowメソッドはwindowオブジェクトのプロパティのx、100を返してしまいました。これには初見で???となります。それでは以下はどうでしょうか。
なんとアロー関数を持ったyabeオブジェクトのcallNameメソッドはcallメソッドを使用してthisの対象が変わっても同じglobalしか返しません。このthisは常にオブジェクトの外側のグローバルオブジェクトを示しています。それでは以下はどうでしょうか。
functionはfunctionを所有するオブジェクトのthisを参照します。なのでdepthオブジェのfuncメソッドはdepthオブジェクトのthisを参照しますがfuncメソッドの中のinFuncメソッドはdepthオブジェクトのthisまで遡りません。関数内の関数にこれを参照させたい場合は一度変数に代入します。
しかしアロー関数を使用することによりthisで外側のオブジェクトを参照することが可能です。
関数内の関数を定義することでthisの対象が親のオブジェクト自体から外れてしまいます。アロー関数はこういった場合外側のオブジェクトにthisを束縛してくれる役割もあります。アロー関数をいくつネストしても結果は変わりません。
ちなみにアロー関数がオブジェクトのメソッドの中で宣言されているようなアロー関数のthisがグローバルオブジェクトではなくメソッドの所有者であるオブジェクトを示している場合はcallメソッドで呼ばれた場合もthisの対象は変わります。
ブラウザ上でaddEventListenerを使用する際などはクリックされた対象自体を参照したい場合にアロー関数を使用すると思わぬ結果をもたらすことになります。
これを逆手にとってオブジェクトにイベントを登録させる際にaddEventListenerのthisの参照先をオブジェクトのプロパティに参照させることも可能です。
thisの参照をオブジェクトに参照させることに成功しました。これでインスタンスを作成した場合も格インスタンスをthisで参照することができます。class構文に馴染みがない場合は以下のprototype構文も同じ内容になります。
今回アロー関数だけで長くなったので他は次回に続きます。多分。