Angular をやっていて、デコレータが出てきた。Java などでいうアノテーションだが、どのような仕組みなのかスッキリしないので、ちょっとだけ試して見た。
クラスの Decorator
Decorator の実態は関数だ。クラスのデコレータはコンストラクタに対してかける。
ここでは、新しいプロパティを追加定義している。
function classDecorator<T extends {new(...args:any[]):{}}>(constructor:T) {
return class extends constructor {
newProperty = "new property";
hello = "Overriden";
}
}
@classDecorator
class Greeter01 {
hello: string
constructor(m: string){
this.hello = m;
}
}
console.log(new Greeter01("This is it"));
実行結果
class_1 { hello: 'Overriden', newProperty: 'new property' }
メソッドのデコレータ
メソッドのデコレータで、ロガーを書いてみる。おそらく、リフレクションとか使うと、
引数とかもダンプできそうだが、元々の目的と異なるので、ここでは深堀しない。ポイントは、関数の引数に、ターゲットのオブジェクト、呼ばれたメソッド名、そして、プロパディディスクリプタが呼ばれた時に引き渡される。関数を呼び出しているので、このケースでは、descriptionはnull になった。
function logger(value: boolean) {
return function (target: any, propertyKey: string, description: PropertyDescriptor) {
if (value === true) {
console.log(propertyKey + " is called");
console.log(Object.getOwnPropertyDescriptor(target, propertyKey));
}
}
}
class Greeter02 {
@logger(true)
greet(message:string) {
console.log("I'm Greeter 02 " + message);
}
}
var greeter = new Greeter02();
greeter.greet("hello");
実行結果
{ value: [Function],
writable: true,
enumerable: true,
configurable: true }
I'm Greeter 02 hello
まとめ
ざっくりと、デコレータのイメージがつかめた。ただし、ここを本気でやろうと思ったら、リフレクションの深堀が必須っぽいので、今日はこの辺にしておく。