国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

使用AOP改善javascript代碼

2019-11-20 12:34:26
字體:
供稿:網(wǎng)友

Aop又叫面向切面編程,用過spring的同學(xué)肯定對(duì)它非常熟悉,而在js中,AOP是一個(gè)被嚴(yán)重忽視的技術(shù)點(diǎn),這篇就通過下面這幾個(gè)小例子,來說說AOP在js中的妙用.

1, 防止window.onload被二次覆蓋.
2,無侵入的統(tǒng)計(jì)代碼.
3, 分離表單請(qǐng)求和校驗(yàn).
4,給ajax請(qǐng)求動(dòng)態(tài)添加參數(shù).
5,職責(zé)鏈模式.
6, 組合代替繼承.

先給出before和after這2個(gè)“切面”函數(shù). 顧名思義,就是讓一個(gè)函數(shù)在另一個(gè)函數(shù)之前或者之后執(zhí)行,巧妙的是,before或者after都可以和當(dāng)前的函數(shù)公用this和arguments, 這樣一來供我們發(fā)揮的地方就多著了.

/

處理window.onload被二次覆蓋.

前段時(shí)間看到QQ群里有個(gè)人問問題,要改寫window.onload, 怎么才能不把以前的window.onload函數(shù)覆蓋掉.

最原始的方案肯定是直接在原來的window.onload里添上你的新代碼.

/

這樣的壞處非常明顯,需要去改動(dòng)原有的函數(shù), 是侵入性最強(qiáng)的一種做法.

另外一種稍微好點(diǎn)的方案是用中間變量保存以前的window.onload;

/

這樣一來,多了一個(gè)討厭的中間變量__onload, 來管理它也要花費(fèi)一些額外的成本.

試想一下這個(gè)場(chǎng)景,當(dāng)人覺得天氣冷,出門的時(shí)候很自然選擇穿上一件貂皮大衣,而不是把自己的皮扯掉換成貂皮. 動(dòng)態(tài)裝飾的好處就體現(xiàn)出來了,完全不會(huì)侵入之前的函數(shù).

/

無侵入的統(tǒng)計(jì)代碼

本身跟邏輯沒有任何關(guān)聯(lián)的統(tǒng)計(jì)代碼要被硬插進(jìn)函數(shù)里, 這點(diǎn)相信很多搞過上報(bào)的同學(xué)都很不爽. 比如下面這段代碼, 用來統(tǒng)計(jì)一個(gè)創(chuàng)建1000個(gè)節(jié)點(diǎn)的函數(shù)在用戶的電腦上要花費(fèi)多少時(shí)間.

/

用aop的方式,不再需要在函數(shù)內(nèi)部做改動(dòng),先定義一個(gè)通用的包裝器.

/

只要一行代碼,便能給任何函數(shù)都加上統(tǒng)計(jì)時(shí)間的功能.

/

分離表單請(qǐng)求和校驗(yàn)

我們?cè)谔峤槐韱沃敖?jīng)常會(huì)做一些校驗(yàn)工作,來確定表單是不是應(yīng)該正常提交. 最糟糕的寫法是把驗(yàn)證的邏輯都放在send函數(shù)里面.

/

而更好的方式是把所有的校驗(yàn)規(guī)則用策略模式放到一個(gè)集合里,返回false或者true來決定是否通過驗(yàn)證. 這樣可以隨意的選擇和更換校驗(yàn)規(guī)則.

/

這樣還有一個(gè)缺點(diǎn),校驗(yàn)和發(fā)送請(qǐng)求這2個(gè)請(qǐng)求耦合到了一個(gè)函數(shù)里面, 我們用aop來把它們分離開來, 把validata做成插件化,真正的即插即用. 只需把send函數(shù)改成:

/

過最前面Function.prototype.before的代碼不難看出,我們約定,當(dāng)前一個(gè)函數(shù)返回false, 就會(huì)阻斷下一個(gè)函數(shù)的執(zhí)行, 所以當(dāng)validata返回false的時(shí)候, 便不再繼續(xù)執(zhí)行send. 而因?yàn)橹疤岬降腷efore函數(shù)可以和當(dāng)前函數(shù)公用this和arguments, 所以value參數(shù)也能順利的傳遞到validata函數(shù)里.

給ajax請(qǐng)求動(dòng)態(tài)添加參數(shù)

第一個(gè)例子里window.onload是用的after后置裝飾, 這里是用before前置裝飾. 在ajax請(qǐng)求之前動(dòng)態(tài)添加一些參數(shù).

我們遇到過很多跨域的請(qǐng)求, jsonp和iframe都是很常用的方式. 之前在我們的項(xiàng)目里,用參數(shù)retype=jsonp表示是jsonp請(qǐng)求, retype=iframe表示是iframe請(qǐng)求. 除此之外這2個(gè)請(qǐng)求的參數(shù)沒有任何區(qū)別. 那么可以用before把retype參數(shù)動(dòng)態(tài)裝飾進(jìn)去.

先定義一個(gè)ajax請(qǐng)求的代理函數(shù)./

這個(gè)函數(shù)里面沒有邏輯處理和分支語句,它也不關(guān)心自己是jsonp請(qǐng)求還是iframe請(qǐng)求. 它只負(fù)責(zé)發(fā)送數(shù)據(jù), 是一個(gè)單一職責(zé)的好函數(shù).

接下來在發(fā)送請(qǐng)求前放置一個(gè)before裝飾器.

/

開始發(fā)送請(qǐng)求:

/

職責(zé)鏈模式.

職責(zé)鏈模式在js中典型的應(yīng)用場(chǎng)景是事件冒泡. 將所有子節(jié)點(diǎn)和父節(jié)點(diǎn)連成一條鏈,并沿著這條鏈傳遞事件,直到有一個(gè)節(jié)點(diǎn)能夠處理它為止. 職責(zé)鏈模式是消除過多的if else語句的神器.

拿最近做的一個(gè)需求來舉例, 有個(gè)文件上傳的功能, 提供了控件,html5, flash, 表單上傳這4種上傳方式. 根據(jù)它們的優(yōu)先級(jí)以及瀏覽器支持情況來判斷當(dāng)前選擇哪種上傳方式. 在我進(jìn)行改造之前,它的偽代碼大概是這樣:

/

當(dāng)然實(shí)際的代碼遠(yuǎn)不只這么多,其中還包括了各種控件初始化,容錯(cuò)等情況。有天我需要屏蔽掉flash,看起來是很簡(jiǎn)單的需求,但難度實(shí)際跟在心臟旁邊拆掉一根毛線血管類似.

如果試試職責(zé)鏈模式呢, 看看事情將變得多簡(jiǎn)單:

第一步先改寫之前的after函數(shù),使得返回一個(gè)對(duì)象時(shí)阻斷職責(zé)鏈的傳遞,而返回null時(shí)繼續(xù)傳遞請(qǐng)求。

/

接下來把每種控件的創(chuàng)建方式都包裹在各自的函數(shù)中, 確保沒有邏輯交叉和相互污染.

/

最后用職責(zé)鏈把它們串起來:

/

可以預(yù)見,某天我又需要屏蔽掉flash, 那時(shí)的我只需要改動(dòng)這一行代碼. 改成:

/

組合代替繼承

很多時(shí)候我們?cè)谠O(shè)計(jì)程序的時(shí)候,會(huì)遇到使用組合還是繼承的問題. 通常來講, 使用組合更靈活輕巧. 還是拿之前文件上傳來舉例.

我定義了一個(gè)超類Upload, 衍生出4個(gè)子類.
Plugin_Upload, Html5_Upload, Flash_Upload以及Form_Upload.

Plugin_Upload會(huì)繼承父類,得到Upload的大部分功能, 然后對(duì)控件上傳的一些特性進(jìn)行個(gè)性定制. 比如其它3種上傳方式都是選擇文件后便開始上傳. 而控件上傳在開始上傳之前會(huì)經(jīng)過一輪文件掃描.

第一種做法是Plugin_Upload繼承Upload, 然后重寫它的start_upload方法.

/

用更輕的組合方式, 可以直接給原來的start_upload函數(shù)裝飾上掃描功能, 甚至不需要衍生一個(gè)額外的子類.

/

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 兴业县| 泰来县| 中山市| 临洮县| 宜兰市| 团风县| 洛南县| 满洲里市| 天镇县| 太谷县| 崇州市| 潼南县| 乌鲁木齐县| 莆田市| 远安县| 安达市| 怀安县| 永登县| 南汇区| 丰镇市| 绵竹市| 安徽省| 百色市| 马龙县| 新绛县| 河北区| 卓资县| 城步| 德令哈市| 盘山县| 宁德市| 华容县| 淳安县| 聂拉木县| 竹北市| 宜兴市| 仁寿县| 舞钢市| 兴仁县| 甘谷县| 靖州|