2017年8月6日日曜日

ECMAScriptでメソッド呼び出し時に引数をいじるデコレータ

ふと、JavaScriptでクラスのメソッドをコールするときにこっそり特定の値を追加したいという衝動にかられたので調べてみました。


デコレータを使います

ES7の提案段階の機能、デコレータで実現してみます。

まずはプラグイン babel-plugin-transform-decorators-legacy をインスコ。
$ npm install --save-dev babel-plugin-transform-decorators-legacy
"legacy"とついているのは、このプラグイン自体が古いからではなく、仕様がまだ不安定で将来変わる可能性が大いにあるから今のうちにlegacyってつけてるんだそうな。

legacyがついてないプラグインもあるけど、これを使おうとすると「legacy版使え」って言われます。

つぎに .babelrc でプラグインの設定。
{
  "plugins": ["transform-decorators-legacy"]
}
最後にこんな感じのコードをかいてみましょう。
// 引数の最初にぬるぽを追加するデコレータ
function nullpo(target, name, descriptor) {
    const value = descriptor.value;
    if (typeof value !== "function") {
        // 関数じゃなければスルー
        return;
    }
    descriptor.value = (...args) => {
        // nullpoを追加
        value.call(target, "nullpo", ...args);
    };
}

class MyClass {
    @nullpo
    myMethod(...args) {
        // 試しに引数を出力してみようか
        console.log(args);
    }
}

const myClass = new MyClass();
myClass.myMethod("ga");
ポイントは、プロパティディスクリプタの value を書き換えること。
同じ要領で、引数の変更や削除もできます。

ECMAScriptではまだ提案段階ですが、TypeScriptが先取りしちゃいました。アスペクト指向に超便利。早く正式採用してくれないかな。

0 件のコメント:

コメントを投稿