Decorator
Overview
Decorator(デコレーター)についてまとめるセクション
デコレーターとはクラスやメソッドなどの機能を拡張するための仕組み
見た目は @decorator という形で、アノテーション的に見えるけど、本質は関数になる。
最終的にはランタイムで動作し、if文と違ってクラスの定義自体に対して拡張する(=メタプログラミング)」のが特徴
function MyDecorator(target) {
console.log("decorating:", target.name);
}
@MyDecorator
class MyClass {}
// この @MyDecorator は、「MyClass に対して MyDecorator 関数を適用する」というだけの話。
// つまり、MyDecorator(MyClass) と同じことをやってる。
ヒント
実行時に条件分岐するだけなら if文でいい。
クラス定義そのものに対する拡張(メタ情報付与など)はデコレーターの方が楽という考え方
関数でやる vs デコレーターでやる
ただし、デコレーターは「書き方として楽」なのと、クラスの定義と一緒にスッキリ見せられる というメリットが大きい。
- デコレーターの正体は「ただの関数呼び出し」
- 便利なのは見た目(構文糖)とメタデータ一括管理の面
- 「別に関数で組み込めばよくない?」→ その通り!
- デコレーターは見た目がスッキリ
- 宣言的に「このクラスはこう拡張する」と明示できる
- 大きなフレームワーク(NestJSやTypeORMなど)でも一貫してこういう記述を使うので可読性・統一感が上がる
ただ、言ってしまえば「関数を作って組み込む」っていう根本の仕組みは一緒。
だから、「複雑すぎる/好みじゃない」と感じるなら、素直に関数呼び出しでやるのもぜんぜんアリ。
@MyDecorator
class MyClass {}
// でもこれ、実際はこう書いてるのと同じ
MyClass = MyDecorator(MyClass) || MyClass;
関数で拡張するパターン
「関数作って組み込めばよくない」を例にしたコード
function enhance(ClassDef) {
// クラスに新機能を付加するなど
ClassDef.prototype.newMethod = function() { console.log("new!"); };
return ClassDef;
}
class MyClass {}
const EnhancedClass = enhance(MyClass);
デコレーターで書くパターン
デコレーターの方がスッキリ書ける。
function enhance(target) {
target.prototype.newMethod = function() { console.log("new!"); };
}
@enhance
class MyClass {}