JavaScript Decoratorsについて
Decorators文法を使うことでクラスの内部実装を変更することなく、クラス変数やクラスメソッドを外部から拡張・上書きすることができます。
これはJavaなどでいうDI(Dependency Injection)に該当します。
babel-plugin-transform-decorators-legacyを使うことでDecoratorsを変換してくれます。
yarnインストール済み前提で、
下記コマンドでbabel-plugin-transform-decorators-legacyをインストールします。
$ yarn init -y
$ yarn add --dev babel-plugin-transform-decorators-legacy
Decoratorsのサンプルは以下となります。
decorators.js
// 対象のクラス
@isTestable(true)
class MyClass {
@log('メソッドコール1')
test1() {
console.log('test1')
}
@log('メソッドコール2')
test2(val1, val2) {
console.log('test2',val1, val2)
}
}
// クラスデコレーター定義
function isTestable(value) {
return (target) => {
return class extends target {
constructor() {
super()
// 変数拡張
this.isTestable = value
}
// メソッド拡張
method() {
console.log('テスト')
}
}
}
}
// クラスメソッドデコレーター定義
function log(value){
return (target, property, descriptor) => {
const origin = descriptor.value
descriptor.value = (...arg) => {
console.log(value)
origin(...arg)
}
}
}
const myclass = new MyClass()
// MyClassを直接操作せずにクラスデコレータから変数値を挿入する。
console.log(myclass.isTestable)
// MyClassを直接操作せずにクラスデコレータからメソッドを定義する。
myclass.method()
// MyClassを直接操作せずにクラスメソッドデコレータからメソッドをフックする。
myclass.test1()
// MyClassを直接操作せずにクラスメソッドデコレータからメソッドをフックする(引数付)
myclass.test2('a','b')
今回はCLIからトランスパイルするので.babelrcを作成します。
.babelrc
{
"plugins": ["transform-decorators-legacy"]
}
下記のコマンドでトランスパイルします。
babel --plugins transform-decorators-legacy decorator.js > compile.js
トランスパイル後のコードを実行すると、
MyClassのほうの実装を変更することなく、
decoratorsにより、クラスの拡張およびメソッドのフックがされていることが確認できます。
$ node compile.js
true
テスト
メソッドコール1
test1
メソッドコール2
test2 a b