Part18:メタプログラミング

海未「さて、今回で最終回になります。ProxyとReflectionという、メタプログラミングのための機構を見てみましょう」


プロキシ

海未「Proxyは、JavaScript言語が提供している何らかの処理に対して割り込みをかけるものです」
ことり「割り込み、って?」
海未「何らかの処理、と漠然と言ってしまいましたが、プロパティの値へのアクセスに対する割り込みの例を見てみましょう」

海未「この例では、存在しないプロパティにアクセスした際、undefinedの代わりに”alpaca”を返すよう、割り込みをかけています」
ことり「p.ageとかの結果を変えられちゃうの?」
海未「そうです。上半分のhandlerが、割り込ませる処理を持ったハンドラオブジェクトで、Proxyオブジェクトがクライアントコードと対象オブジェクトの仲介をしてハンドラを実行します」
穂乃果「えーと、どうやってるの?」
海未「まずプロキシの動きからいきましょう。Proxyコンストラクタ関数の第1引数は割り込み対象のオブジェクト、第2引数は割り込ませる処理を持ったハンドラです」
穂乃果「{name: "honoka"}ってオブジェクトに割り込みするんだよね」
海未「そうです。ここで生成されたプロキシは、対象オブジェクトと見た目は同じように振る舞います」
穂乃果「うん。それでp.nameで値が取れるんだよね」
海未「しかし実際には、プロキシに対してp.nameを行うと、ハンドラで定義されている処理が実行されているのです」
穂乃果「な、なんだってー!」
海未「ハンドラにgetという名前のメソッドがありますね」
ことり「うん」
海未「プロキシに対してプロパティの取得を行うと、そのgetメソッドが実行されるのです」
ことり「あ、これでプロパティがなかったらアルパカさんを返してるんだ」
海未「このgetメソッドはトラップと呼ばれます。プロパティ取得時のget以外にも、プロパティ設定時のsetや存在検査のhasfor...ofで列挙するときのiterateなど様々な種類があります」

海未「よく使われそうな例としては、プロパティの値の検証があると思います」

海未「このトラップは、ageプロパティの設定時に値の妥当性を検査するものです」
ことり「0以上の整数じゃないと、めっ!なんだね」
穂乃果「これは便利そうだねっ!」
海未「・・・・・・」

海未(穂乃果、穂乃果・・・その)
穂乃果(どうしたの海未ちゃん)
海未(ことりに、もう何度か「めっ!」と言われたいのですが)
穂乃果(もう知らないよそんなのっ!)


取り消し可能プロキシ

海未「プロキシは取り消しが可能です」

海未「プロキシの作成時にProxy.revocableを使うと、取り消し可能なプロキシができます。必要がなくなったら、revokeを呼ぶと以降使用できなくなります」


リフレクション

海未「では最後にReflectionの動きを見てみましょう。これは、言語が提供している機能を関数として扱えるようにするものです」
穂乃果「うう、メタな話は苦手だよう・・・」

海未「このように、言語機能を関数に置き換えられるのが分かるかと思います」
ことり「やってることは、わかるけど・・・」
海未「Reflectのメソッドにはプロキシのトラップと同じものが用意されています。ですから、プロキシと組み合わせて使うとよいようです」

海未「さきほどのエラーチェックの例ですが、チェックが終わったらReflect.setを呼び出すことで、本来のプロパティ設定の動作を行うことができます」
ことり「プロキシはあくまで割り込みだから・・・割り込み処理が終わったら、ちゃんと本来の動作もしないといけないんだね」
海未「setであればtarget[prop] = value;と書けば済みますが、トラップによっては自分で実装するのが大変なものもありますから、そこはReflectの使いどころですね」

海未「関数を引数に取る関数はこれまでに見てきましたね」
穂乃果「高階関数、だっけ」
海未「はい。そこには関数は何でも渡すことができますが、例えばinを使う式は関数ではありませんから、プロパティの存在検査処理はそのままでは渡せないことになります」
穂乃果「存在検査をする関数を作らなきゃいけないってことかな」
海未「そうなりますね。しかし、Reflect.hasであれば同じことをする関数ですから、他の関数に渡したり、変数に代入しておいたり、といったことができます」


海未「このようにプロキシやリフレクションを使って、JavaScriptの言語機能を拡張していくことができます。高等テクニックになりますが、他の言語機能を使いこなせるようになったらぜひ挑戦してみてください」
ことり「難しいところもあったけど、ちゃんと復習すれば何とかなるよ、ね、穂乃果ちゃん?」
穂乃果「関数とか継承とかはちゃんと見返さないと無理っぽい~」
海未「言語仕様編はこれで終わりますが、ここまでで学んだことはあくまで言語仕様ですから、実行環境に依存した部分も学習しないと実際のプログラムは書けません」
穂乃果「それ、まだまだ勉強しないといけないってことだよね?」
海未「JavaScriptはただ書くだけなら簡単です。しかし、そのレベルで書かれたコードがどれだけの保守プログラマの心を折ってきたか・・・」
ことり「迷惑かけないためにも、ちゃんと勉強しないとね♪」

海未「このあと、クライアントサイドに行くかサーバサイドに行くかは考え中です。少しお待ちくださいね」

穂乃果「では中締めということで。お相手は高坂穂乃果とっ!」
ことり「南ことりと♪」
海未「園田海未でした♡」
3人「「「まったねーっ!!」」」


LINEで送る
Pocket


返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です