AOP(面向切面程式設計)的主要功能是把一些跟核心業務邏輯模組無關的功能抽離出來,這些跟業務邏輯無關的功能通常包括日誌統計、安全控制、異常處理等。把這些功能抽離出來之後, 再透過「動態織入」的方式摻入業務邏輯模組中。本文就為大家分享一篇JavaScript實作AOP的方法(面向切面程式設計,裝飾者模式),具有很好的參考價值,希望對大家有幫助。
AOP能為我們帶來什麼好處?
AOP的好處首先是可以保持業務邏輯模組的純淨和高內聚性,其次是可以很方便地重複使用日誌統計等功能模組。
JavaScript實作AOP的思路?
通常,在JavaScript 中實作AOP,都是指把一個函數「動態織入」到另外一個函數之中,具體的實作技術有很多,下面我用擴充Function.prototype 來做到這一點。請看下面程式碼:
Function.prototype.before = function (beforefn) { var _self = this; //保存原函数引用 return function () { //返回包含了原函数和新函数的"代理函数" beforefn.apply(this, arguments); //执行新函数,修正this return _self.apply(this, arguments); //执行原函数 } }; Function.prototype.after = function (afterfn) { var _self = this; return function () { var ret = _self.apply(this, arguments); afterfn.apply(this, arguments); return ret; } }; var func = function () { console.log("2") } func = func.before(function () { console.log("1"); }).after(function () { console.log("3"); } ) func();
執行結果如下:
我把負責列印數字1和列印數字3的兩個函數透過AOP的方式動態植入func函數。透過執行上面的程式碼,我們看到控制台順利地回傳了執行結果1、2、3。
這種使用AOP的方式來為函數添加職責,也是JavaScript語言中的一種非常特別的巧妙的裝飾者模式實現,下面我們來試試Function.prototype.before的威力,請看下面程式碼:
Function.prototype.before = function (beforefn) { var __self = this; // 保存原函数的引用 return function () { // 返回包含了原函数和新函数的"代理"函数 beforefn.apply(this, arguments); // 执行新函数,且保证 this 不被劫持,新函数接受的参数 // 也会被原封不动地传入原函数,新函数在原函数之前执行 return __self.apply(this, arguments); // 执行原函数并返回原函数的执行结果, 2 // 并且保证 this 不被劫持 } } Function.prototype.after = function (afterfn) { var __self = this; return function () { var ret = __self.apply(this, arguments); afterfn.apply(this, arguments); return ret; } }; document.getElementById = document.getElementById.before(function(){ alert (1); }); var button = document.getElementById( 'button' );
執行結果:
我們給document.getElementById()做了一些裝飾,以後我們每次呼叫這個方法之前都會先執行alert("1")這句話,但請注意我們這語句並不是寫在了document.getElementById()這個方法的源碼中,而只是在他的外部給他加了裝飾,這樣帶來好處就是我們可以在不改變原方法的源碼的情況下為他添加一些新的行為。國際慣例,舉個栗子:
我的同事寫了一個函數可以輸出當前時間,而我現在的需求是輸出當前天氣之後再輸出當前時間,下面有兩種解決思路:
(1)傳統解決方法: 拿同事的函數過來,找出他輸出時間的程式碼,在這些程式碼之前加入輸出當前天氣的程式碼
(2)裝飾者模式解決方法:拿同事的函數過來,不用看他的原始碼,直接給他的函數裝飾一下,裝飾的東西也就是輸出當前天氣的程式碼。
兩種方法都解決了問題,但是他們的出發點是完全不同的:
(1)方法是改造原函數的內部,我們就需要去理解原始碼,然後做修改。
(2)方法是為原函數增加了一層外套,我們根本不用管原本函數的內部實作。
現在又有了新的需求:在輸出目前時間之前,先輸出當前溫度
(1)方法,我們在第一個需求已經把同事的程式碼改的面目全非了,現在又要重新理解函數內部,並加以修改(刪除輸出目前天氣的程式碼,然後加入輸出目前溫度的程式碼)。
(2)方法,同事原本的函數是沒有改變的,我們現在給同事的函數換一件套(輸出目前溫度)就可以了。
相關推薦:
以上是JavaScript實作AOP實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!