我的理解,某些場景須要在不改變原有類和屬性的基礎上擴展一些功能,因此裝飾器就出現了。java
裝飾器的寫法是在類或類屬性以前,加個方法名。學過java
的同窗應該比較熟悉這種寫法,Spring
中鋪天蓋地都是註解。具體細節處處都是,就不贅述了。node
不過截止到今天(2019年8月),遺憾的是nodejs
還未原生支持,仍然須要babel
編譯。api
忽然想到用裝飾器,固然是有業務須要。寫了一個api
類,全部暴露的函數都須要進行一步初始化操做。但初始化代碼又不歸我控制,且是異步接口請求,不能當即執行,這就致使每一個函數都要調用一遍這個init
方法。由於加了緩存,每一個都要判斷有沒有緩存,比較噁心。緩存
通常用這個日誌模塊來舉例,不過它是同步的babel
class Math { @log add(a, b) { return a + b; } } function log(target, name, descriptor) { var oldValue = descriptor.value; descriptor.value = function() { console.log(`Calling "${name}" with`, arguments); return oldValue.apply(null, arguments); }; return descriptor; } const math = new Math(); // passed parameters should get logged now math.add(2, 4);
let init = 0; class Maths { @log add (a, b) { return a + b + init; } } function log (target, name, descriptor) { let oldValue = descriptor.value; descriptor.value = function (...args) { //有時候,arguments指向不對,多是babel的鍋? console.log(`Calling "${name}" with`, args); return new Promise((resolve) => { setTimeout(function () { // args = [...args, 100]; init = 100; resolve(oldValue.apply(target, args)); //this指向 }, 100); }); }; return descriptor; } const math = new Maths(); (async () => { let a = await math.add(2, 4); console.log(a); })();
在具體函數前加了裝飾器後,會先執行log
方法,這樣緩存的變量就修改了。雖然結果變成異步的,但也知足個人須要了。app