[TypeScript] 方法裝飾器 (Method Decorators)

  • 678
  • 0

TypeScript 的 裝飾器 (Decorators) 介紹,
裝飾器可以分為類別裝飾器(Class Decorators)、屬性裝飾器(Property Decorators)、方法裝飾器(Method Decorators)、參數裝飾器(Parameter Decorators)。

裝飾器的寫法是在裝飾器的名字前面加上@
可以將參數傳入裝飾器,也可以不傳參數。

@DecoratorExample
@DecoratorLog('write log') 

接下來介紹裝飾器的實作,
可以分為兩種,一種就是有傳參數的,另一種就是沒有傳參數的。

先介紹沒有傳參數的:

function DecoratorExample(target: Function) { 
    //coding 
}

有傳參數的:

function DecoratorLog(logText: string) { // logText就是傳進來的參數'write log' 
    return function(target: Function) { 
        // coding
    } 
}

要特別注意的是,有傳參數的裝飾器需要回傳一個 function。


這篇文章要介紹的是方法裝飾器(Method Decorators)

首先建立一個類別,並且使用了 log 當作裝飾器,
讓 doubleNumber 方法被使用時,印出 console log。

class MyClass {
    @log
    doubleNumber(input: number) {
        return input * 2;
    }
}

var testMyClass = new MyClass().doubleNumber(5);

在使用方法裝飾器前,我們必須先宣告和實作出來:

function log(target: Function, key: string, descriptor: any) { 
    return {
        value: function (...args: any[]) {  //args 是指 doubleNumber 的參數,也就是 input
            var fooParameter = args.map(a => JSON.stringify(a)).join();
            var result = descriptor.value.apply(this, args);  //就是執行 doubleNumber 這個 method 後,會得到的值
            console.log(`Call: ${key}(${fooParameter}) => ${result}`);//Call: doubleNumber(5) => 10
            return result;
        }
    };
}

每當我們執行類別 MyClass 中 doubleNumber 這個 method,就會觸發 log 方法裝飾器,
方法裝飾器需要被傳入的參數有下列三個
target : 被裝飾的 method
key : 被裝飾 method 的名字,也就是範例中的 doubleNumber
descriptor : 被裝飾 method 的 屬性描述 (PropertyDescriptor)

讓我們來看看 typescript 轉換成 javascript 的 code

var MyClass = (function () {
    function MyClass() {
    }
    MyClass.prototype.doubleNumber = function (input) {
        return input * 2;
    };
    __decorate(
		[log],              // decorators
		MyClass.prototype,  // target
		"doubleNumber",     // key
		null		    // descriptor
	);
    return MyClass;
}());

如果是沒有加上 @log 方法裝飾器的話,
typescript 轉換成 javascript 的 code 就會變成下面的範例程式碼

var MyClass = (function () {
    function MyClass() {
    }
    MyClass.prototype.doubleNumber= function (input) {
        return input * 2;
    };
    return MyClass;
}());

方法裝飾器可以讓 method 有額外的功能,
而不影響原本 method 要達成的事情,
像是範例中的 doubleNumber ,這個 method 想達到的事情就是將數字乘以 2,
因為想知道 method 被使用的狀況,所以使用了方法裝飾器來做紀錄,
除了用來寫 log 做紀錄,也可以用來做 method 前的權限檢查等等之類的延伸功能。

以上是方法裝飾器(Method Decorators)的簡單介紹,
之後會再陸續介紹其他種的裝飾器。