ES2015のProxyを使った関数呼び出しのフック

ES2015にはProxyという仕組みがある。

Proxyを使うことでオブジェクトへの書き込みや読み込みをフックすることができ、メタプログラミング的なことがJavaScript上で実現できるようになる。

例えば、関数呼び出しをフックして呼び出し前に何か別の処理をしたい、と思ったら以下のように書ける。

const obj = {
  foo: (x) => {
    console.log(x);
  }
};

const proxy = new Proxy(obj, {
  get: function(target, name) {
    const targetObj = target[name];
    if (typeof targetObj === 'function') {
      return function(...args) {
        console.log(`call ${name} ${args}`);
        const result = targetObj.apply(this, args);
        return result;
      };
    } else {
      return targetObj;
    }
  }
});

window.onload = () => {
  proxy.foo(42);
}

Proxyのgetハンドラで値の読み込みをフックし、関数を読み込もうとしたら別の関数に差し替える。差し替えた関数の中ではapplyで元の関数を呼び出すけど、その前や後に任意の処理を挟み込むことができる。

ちなみにES5の制約でBabelはProxy未サポートなのでブラウザが対応しないかぎりProxyは使えない。

今までProxyはFirefoxかEdgeでしか使えなかったのだけど、Chromeも49から対応してくれるらしい。

だとするとそろそろProxyを使ったメタプログラミングに手を出してもいいかなあとも思う。あとTypeScriptでもES6ターゲットにすればProxy書いても文句言わないので使えそうだ。