AOP裝飾函式與小T的情愫
有一天,老大見程式員小T的核心邏輯程式碼相當冗雜,核心邏輯模組和一些無關的功能融成一團,就告訴小T,讓他嘗試把日誌統計,異常處理模組從和核心邏輯模組中抽離出來,對於剛入職經驗不足的小T來說,猶如晴天霹靂。小T前思後想,還好大學期間讀了不少程式設計相關的書籍有些功底,既然目的是想把一些日誌統計、異常處理這些和核心邏輯程式碼無關的抽離出來,他靈機一閃,心想這不是面向切面程式設計(AOP)嘛,老大果然是老司機,把和核心邏輯模組無關的功能抽離出來,業務邏輯模組就清晰了很多,還能夠複用日誌統計、日常處理等這些功能模組,真是兩全其美啊!
於是小T開始了實現AOP之旅,心想核心業務模組和其他模組,那我就抽象成兩個函式,既然需要在核心業務模組中使用異常處理這些功能,我應該把異常處理函式動態織入到其中,想到這小T不禁欣喜了一番,但是馬上又陷入了思考,我應該怎麼把一個函式”動態織入”到另一個函式中呢?小T之前對於原型的掌握相當紮實,於是他想我可不可以擴充套件Function的原型來把一個函式”動態織入”另一個函式呢.小T決定試一下,於是便敲敲打打:
Function.prototype.before = function(){ }
小T想,我需要一個原函式(核心邏輯模組)和新函式(日誌統計),我可以把”動態織入”的新函式作為引數傳遞,然後返回原函式和新函式的”代理”函式,然後執行,這樣我不就可以在原函式之前執行新函式啦。既然Function.prototype.before裡有原函式又有傳遞的新函式引數,新函式被執行後this的指向可能會被劫持,所以他想到了先儲存一下原函式引用
Function.prototype.before = fcuntion(beforefn){ var _self = this;//儲存原函式的引用 return function(){//返回包含了原函式和新函式的”代理“函式 } }
然後小T想,既然是before要讓新函式在原函式之前執行,return function(){}我應該怎麼處理可以讓兩個函式執行並且不會導致this被劫持呢,小T說如果我直接執行beforefn(),那麼this指向會被劫持,小T想到apply/call可以很自然的控制/重寫this值,以便定義呼叫函式時確定this指向哪個物件,決定用apply試試:
Function.prototype.before = fcuntion(beforefn){ var _self = this; return function(){ beforefn.apply(this,arguments); // 執行新函式,且保證this不被劫持,新函式接受的引數會被原封不會的傳入原函式,新函式在原函式之前執行 return _self.apply(this,arguments) //執行原函式並返回原函式執行結果,並保證this不被劫持 } }
寫到這裡,小T有些激動