今天來實作一個 Decorator 的例子,當我們在畫面上有一個按鈕,想要透過點擊該按鈕觸發 showMessage()
顯示 Printer
實例裡面的 message
,但因為是 event listener 的關係,這樣點擊會是 console
undifined
的,因為 this
是指向 event,而非 class。在 JavaScript 我們會寫成 p.showMessage.bind(p)
確保 this
的指向,但也可以透過 Decorator 來實現這件事。
function Autobind(target: any, methodName: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
const adjDescriptor: PropertyDescriptor = {
configurable: true,
enumerable: false,
get() {
const boundFn = originalMethod.bind(this);
return boundFn;
}
};
return adjDescriptor;
}
class Printer {
message = 'This works!';
@Autobind
showMessage() {
console.log(this.message);
}
}
const p = new Printer();
p.showMessage();
const button = document.querySelector('button')!;
button.addEventListener('click', p.showMessage);
透過 Method Decorator,我們可以從 descriptor 拿到 value,它會拿到裝飾的 function,這時候我們定義一個 PropertyDescriptor 型別的物件,從中可以設定他的物件裡面的值,並增加一個 getter
,在裡面使用 bind
方法綁住 this
,其實跟原生的 JavaScript 的方法一樣,這邊是學到了另外一種做法,寫了一次之後不管在哪邊呼叫 showMEssage()
都不用再擔心 this
的指向了,覺得雖然寫了比較多程式碼,但是如果寫了這一次,就不用擔心之後如果有需要用到觸發這個 Printer
class 的 showMessage()
來顯示 message
時卻忘記用 bind
方法還得等執行了之後才能去 debug,或許用 Decorator 保險了許多!
今天的學習筆記到這邊,未來若有時間會再回來撰寫用 Decorator 來實現驗證的功能~謝謝閱讀。:)