[轉載] 用AOP改善JavaScript代碼

Aop又叫面向切面編程,用過spring的同窗確定對它很是熟悉,而在js中,AOP是一個被嚴重忽視的技術點,這篇就經過下面這幾個小例子,來講說AOP在js中的妙用。
1, 防止window.onload被二次覆蓋。
2,無侵入的統計代碼。
3, 分離表單請求和校驗
4,給ajax請求動態添加參數
5,職責鏈模式
6, 組合代替繼承
先給出before和after這2個「切面」函數. 顧名思義,就是讓一個函數在另外一個函數以前或者以後執行,巧妙的是,這2個函數能夠公用this和arguments, 這樣一來供咱們發揮的地方就多着了
處理window.onload被二次覆蓋
前段時間看到QQ羣裏有我的問問題,要改寫window.onload, 怎麼才能不把之前的window.onload函數覆蓋掉
最原始的方案確定是直接在原來的window.onload裏添上你的新代碼
這樣的壞處很是明顯,須要去改動原有的函數, 是侵入性最強的一種作法
另一種稍微好點的方案是用中間變量保存之前的window.onload;
這樣一來,多了一個討厭的中間變量__onload, 來管理它也要花費一些額外的成本
試想一下這個場景,當人以爲天氣冷,出門的時候很天然選擇穿上一件貂皮大衣,而不是把本身的皮扯掉換成貂皮. 動態裝飾的好處就體現出來了,徹底不會侵入以前的函數
無侵入的統計代碼
自己跟邏輯沒有任何關聯的統計代碼要被硬插進函數裏, 這點相信不少搞過上報的同窗都很不爽. 好比下面這段代碼, 用來統計一個建立1000個節點的函數在用戶的電腦上要花費多少時間
用aop的方式,再也不須要在函數內部作改動,先定義一個通用的包裝器
只要一行代碼,便能給任何函數都加上統計時間的功能
分離表單請求和校驗
咱們在提交表單以前常常會作一些校驗工做,來肯定表單是否是應該正常提交. 最糟糕的寫法是把驗證的邏輯都放在send函數裏面
而更好的方式是把全部的校驗規則用策略模式放到一個集合裏,返回false或者true來決定是否經過驗證. 這樣能夠隨意的選擇和更換校驗規則
這樣還有一個缺點,校驗和發送請求這2個請求耦合到了一個函數裏面, 咱們用aop來把它們分離開來, 把validata作成插件化,真正的即插即用. 只需把send函數改爲:
經過最前面Function.prototype.before的代碼不難看出,咱們約定,當前一個函數返回false, 就會阻斷下一個函數的執行, 因此當validata返回false的時候, 便再也不繼續執行send

給ajax請求動態添加參數
第一個例子裏window.onload是用的after後置裝飾, 這裏是用before前置裝飾. 在ajax請求以前動態添加一些參數
咱們遇到過不少跨域的請求, jsonp和iframe都是很經常使用的方式. 以前在咱們的項目裏,用參數retype=jsonp表示是jsonp請求, retype=iframe表示是iframe請求 除此以外這2個請求的參數沒有任何區別. 那麼能夠用before把retype參數動態裝飾進去
先定義一個ajax請求的代理函數
這個函數裏面沒有邏輯處理和分支語句,它也不關心本身是jsonp請求仍是iframe請求. 它只負責發送數據, 是一個單一職責的好函數
接下來在發送請求前放置一個before裝飾器
開始發送請求:
職責鏈模式
職責鏈模式在js中典型的應用場景是事件冒泡. 將全部子節點和父節點連成一條鏈,並沿着這條鏈傳遞事件,直到有一個節點可以處理它爲止. 職責鏈模式是消除過多的if else語句的神器.
拿最近作的一個需求來舉例, 有個文件上傳的功能, 提供了控件,html5, flash, 表單上傳這4種上傳方式. 根據它們的優先級以及瀏覽器支持狀況來判斷當前支持哪一種上傳方式. 在我進行改造以前,它的僞代碼大概是這樣:
固然實際的代碼遠不僅這麼多,其中還包括了各類控件初始化,容錯等狀況。有天我須要屏蔽掉flash控件,看起來是很簡單的需求,但難度實際跟在心臟旁邊拆掉一根毛線血管相似
若是試試職責鏈模式呢, 看看事情將變得多簡單:
第一步先改寫以前的after函數,使得返回一個對象時阻斷職責鏈的傳遞,而返回null時繼續傳遞請求。
接下來把每種控件的建立方式都包裹在各自的函數中, 確保沒有邏輯交叉和相互污染
最後用職責鏈把它們串起來:
能夠預見,某天我又須要屏蔽掉flash, 那時的我只須要改動這一行代碼. 改爲:

組合代替繼承
不少時候咱們在設計程序的時候,會遇到使用組合仍是繼承的問題. 一般來說, 使用組合更靈活輕巧. 仍是拿以前文件上傳來舉例

我定義了一個超類Upload, 衍生出4個子類

Plugin_Upload, Html5_Upload, Flash_Upload以及Form_Upload

Plugin_Upload會繼承父類,獲得Upload的大部分功能, 而後對控件上傳的一些特性進行個性定製. 好比其它3種上傳方式都是選擇文件後便開始上傳. 而控件上傳在開始上傳以前會通過一輪文件掃描

第一種作法是Plugin_Upload繼承Upload, 而後重寫它的start_upload方法
用更輕的組合方式, 能夠直接給原來的start_upload函數裝飾上掃描功能, 甚至不須要衍生一個額外的子類
有些同窗不喜歡擴展Function的原型, 替代方法是給before和after多增長一個參數, 或者像jquery和underscore同樣包裝一層
相關文章
相關標籤/搜索