摘要:獨立出來的函數更加容易被改寫,減少維護成本。例如一個分頁函數,函數接受一個表示挑戰(zhàn)頁碼,在跳轉前需要判斷是否在有效的取值范圍。面向對象設計鼓勵將行為分布在合理數量的更小對象之中。
這是《 javaScript設計模式與開發(fā)實踐 》一書的最后一章"代碼重構"。
以下的一些方法不是必須嚴格遵守的標準,選擇實踐哪些,以及如何實現這都需根據情況而定(是不是有充足時間)
提煉函數如果在函數中有一段代碼可以獨立出來,那么最好把這些代碼放進另外一個獨立的函數當中去。好處有:
避免出現超大型函數。
獨立出來的函數有助于代碼復用。
獨立出來的函數更加容易被改寫,減少維護成本。
獨立出來的函數如果有一個良好的命名,本身就起到了注釋的作用。
例如一個獲取用戶信息的函數,我們還需要打印用戶信息,這種情況下就可以獨立出打印信息的代碼。
var getUserInfo = function() { ajax("http://xxx/userInfo", function(data) { console.log("userId: " + data.userId); console.log("userName: " + data.userName); console.log("nickName: " + data.nickName); }); };
改寫:
var getUserInfo = function() { ajax("http://xxx/userInfo", function(data) { printUserInfo(data); }); }; var printUserInfo = function(data) { console.log("userId: " + data.userId); console.log("userName: " + data.userName); console.log("nickName: " + data.nickName); };合并重復代碼片段
如果一個函數內有一些條件語句,而條件語句內散布了一些重復代碼,就有必要進行合并去重工作。
例如一個分頁函數paging,函數接受一個currpage表示挑戰(zhàn)頁碼,在跳轉前需要判斷currpage是否在有效的取值范圍。
var paging = function(currpage) { if (currpage <= 0) { currpage = 0; jump(currpage); // 跳轉 } else if (currpage >= totalPage) { // 總頁數totalPage currpage = totalPage; jump(currpage); // 跳轉 } else { jump(currpage); // 跳轉 } }
負責跳轉的jump(currpage)在每個條件分支都出現了,所以完全把這句代碼獨立出來:
var paging = function(currpage) { if (currpage <= 0) { currpage = 0; } else if (currpage >= totalPage) { // 總頁數totalPage currpage = totalPage; } jump(currpage); // 跳轉 }把條件語句提煉成函數
在程序設計中,復雜的條件語句是導致程序難以閱讀和理解的重要原因,而且容易增大函數代碼量。例如以一個計算商品價格的getPrice函數,商品計算有個規(guī)則,夏天商品以8折出售。
var getPrice = function(price) { var date = new Date; if (date.getMonth() >= 6 && date.getMonth() <= 9 ) { // 處于夏天 return price * 0.8 } return price; }
其中的條件語句if (date.getMonth() >= 6 && date.getMonth() <= 9 )
如果改寫提煉成一個獨立的函數,既能更準確的表達代碼的意思,函數名又能起到注釋作用。
var isSummer = function() { var dateMonth = (new Date).getMonth(); return dateMonth >= 6 && dateMonth <= 9 ; }; var getPrice = function(price) { var date = new Date; if ( isSummer() ) { // 處于夏天 return price * 0.8 } return price; };合理使用循環(huán)
在函數體內,如果有些代碼是負責一些重復性的工作,那么合理使用循環(huán)不僅可以完成同樣的功能,還可以使代碼量更少,有一段創(chuàng)建XHR對象的代碼,為了簡化代碼,只檢測IE9已下的瀏覽器。
var creatXHR = function() { var xhr; try{ xhr = new ActiveXObject("MSXML2.XMLHTTP.6.0"); } catch(e) { try{ xhr = new ActiveXObject("MSXML2.XMLHTTP.3.0"); } catch(e) { xhr = new ActiveXObject("MSXML2.XMLHTTP"); } } return xhr; }; var xhr = creatXHR();
下面靈活的使用循環(huán),可以得到上面代碼一樣的效果:
var creatXHR = function() { var versions = ["MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP"]; for (var i = 0;i < versions.length; i++) { try{ return new ActiveObject( version[i] ); }catch(e) { } } }; var xhr = creatXHR();提前讓函數退出嵌套條件分支
初學者可能有這樣一個觀念:”每個函數只能有一個入口和一個出口?!爆F代編程語言都會限制函數有一個入口。但是關于”函數只有一個出口”,往往有不一樣的看法。
下面是一個遵守“函數只有一個出口”的代碼。
var del = fucntion(obj) { var ret; if (!obj.isReadOnly) { // 不為只讀才能刪除 if (obj.isFolder) { // 判斷文件夾 ret = deletFolder(obj); } else if (obj.isFile) { // 判斷文件 ret = deletFile(obj); } } return ret; }
嵌套的條件分支語句是代碼維護者的噩夢,如果對函數的剩余部分不感興趣,那就應該立即退出。
我們可以挑選一些條件分支,在進入這些條件分支后,就立即讓函數退出。有一個常見的技巧。在面對一個嵌套的if分支時,我們可以把外層if表達式進行反轉。例如:
var del = function(obj) { if (obj.isReadOnly) { // 反轉表達式 return; } if (obj.isFolder) { return deletFolder(obj); } if (obj.isFile) { return deletFile(obj); } }傳遞對象參數代替過長的參數列表
函數可能接受多個參數,參數越多函數就越難理解和使用。
setUserInfo(1111, "sven", "hangzhou", "male", "137*****") // 可改寫成 setUserInfo({ id: 1111, name: "sven", address: "hangzhou", sex: "male", mobile: "137*****" })
改寫后可以不再關心參數的數量和順序,一般參數控制在4個以內,超過4個就需要轉化成對象形式。
合理使用鏈式調用鏈式調用在調試的時候非常不方便,如果一條調用鏈中有錯誤出現,必須要把這條調用鏈拆開才能定位錯誤出現的地方。
如果該鏈條的結構穩(wěn)定,后期不易發(fā)生修改,使用鏈式調用無可厚非,但是如果該鏈條容易發(fā)生變化,導致調試和維護困難,那么普通調用形式為佳。
分解大型類如果一個類的方法足夠復雜和龐大,那么它完全有必要作為一個多帶帶的類存在。面向對象設計鼓勵將行為分布在合理數量的更小對象之中。
用return退出多重循環(huán)在函數有兩重循環(huán)語句時,我們往往需要在內層循環(huán)中判斷,當達到臨界條件時退出外層循環(huán),有以下實現方式。
設置flag。
var func = function() { var flage = false; for (var i = 0; i < 10; i++) { for (var j = 0; j < 10; j++) { if (i * j > 30) { flag = true; break; } } if (flag === true) { break; } } }
設置循環(huán)標記
var func = function() { outerloop: for(var i = 0; i < 10; i++) { innerloop: for(var j = 0; j < 10; j++) { if (i * j >30) { break outerloop; } } } }
這兩種做法都讓人頭暈目眩,更簡單的做法是直接終止整個方法:
var func = function() { for (var i = 0; i < 10; i++) { for (var j = 0; j < 10; j++) { if (i * j > 30) { return; } } } }
用return直接退出有一個問題,在循環(huán)之后如果還有代碼就無法執(zhí)行:
var func = function() { for (var i = 0; i < 10; i++) { for (var j = 0; j < 10; j++) { if (i * j > 30) { return; } } } console.log(i); // 無法執(zhí)行 }
我們可以把循環(huán)后需要的代碼放到return后面,如果代碼較多,可以提煉成一個多帶帶的函數。
var print = function(i) { console.log(i); }; var func = function() { for (var i = 0; i < 10; i++) { for (var j = 0; j < 10; j++) { if (i * j > 30) { return print(i); } } } };
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://www.ezyhdfw.cn/yun/91730.html
摘要:比如程序會被分解為解析語法分析將詞法單元流轉換成一個由元素逐級嵌套所組成的代表了程序語法接口的書,又稱抽象語法樹。代碼生成將抽象語法樹轉換為機器能夠識別的指令。 showImg(https://segmentfault.com/img/remote/1460000009682106?w=640&h=280); 本文首發(fā)在我的個人博客:http://muyunyun.cn/ 《你不知道的...
摘要:除此以外,讓元素脫離文檔流也是一個很好的方法。因為元素一旦脫離文檔流,它對其他元素的影響幾乎為零,性能的損耗就能夠有效局限于一個較小的范圍。講完重排與重繪,往元素上綁定事件也是引起性能問題的元兇。高性能這本書非常精致,內容也非常豐富。 showImg(https://segmentfault.com/img/bVJgbt?w=600&h=784); 入手《高性能JavaScript》一...
摘要:設計模式與開發(fā)實踐讀書筆記最近利用碎片時間在上面閱讀設計模式與開發(fā)實踐讀書這本書,剛開始閱讀前兩章內容,和大家分享下我覺得可以在項目中用的上的一些筆記。事件綁定暫時這么多,以后會不定期更新一些關于我讀這本書的筆記內容 JavaScript 設計模式與開發(fā)實踐讀書筆記 最近利用碎片時間在 Kindle 上面閱讀《JavaScript 設計模式與開發(fā)實踐讀書》這本書,剛開始閱讀前兩章內容,...
閱讀 3802·2021-11-23 09:51
閱讀 1470·2021-11-10 14:35
閱讀 4079·2021-09-22 15:01
閱讀 1371·2021-08-19 11:12
閱讀 463·2019-08-30 15:53
閱讀 1755·2019-08-29 13:04
閱讀 3507·2019-08-29 12:52
閱讀 3150·2019-08-23 16:14