if else 和 switch && 遞歸 正則表達式
通常來講,if-else 適用於判斷兩個離散的值或者判斷幾個不一樣的值域。若是判斷多於兩個離散值,switch
表達式將是更理想的選擇。算法
如同 咱們在寫sql 總習慣把能夠過濾掉更多的where 放在前面同樣,當 if else 判斷的離散值較多時也因該這麼幹。sql
二分搜索法:shell
if (value == 0){ //要優化的代碼 return result0; } else if (value == 1){ return result1; } else if (value == 2){ return result2; } else if (value == 3){ return result3; } else if (value == 4){ return result4; } else if (value == 5){ return result5; } else if (value == 6){ return result6; } else if (value == 7){ return result7; } else if (value == 8){ return result8; } else if (value == 9){ return result9; } else { return result10; }
if (value < 6){ //二分搜索法 if (value < 3){ if (value == 0){ return result0; } else if (value == 1){ return result1; } else { return result2; } } else { if (value == 3){ return result3; } else if (value == 4){ return result4; } else { return result5; } } } else { if (value < 8){ if (value == 6){ return result6; } else { return result7; } } else { if (value == 8){ return result8; } else if (value == 9){ return result9; } else { return result10; } } }
代碼很簡單 ,效果卻很明顯.瀏覽器
查表法:安全
//define the array of results var results = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10] //return the correct result return results[value];
更加簡單暴力。函數
引用:性能
JavaScript引擎所支持的遞歸數量與 JavaScript調用棧大小直接相關。只有 Internet Explorer例外,它的
調用棧與可用系統內存相關,其餘瀏覽器有固定的調用棧限制。大多數現代瀏覽器的調用棧尺寸比老式瀏
覽器要大(例如 Safari 2調用棧尺寸是 100)。圖 4-2 顯示出主流瀏覽器的調用棧大小。學習
關於調用棧溢出錯誤,最使人感興趣的部分大概是:在某些瀏覽器中,他們的確是 JavaScript 錯誤,可
以用一個 try-catch 表達式捕獲。異常類型因瀏覽器而不一樣。在 Firefox 中,它是一個 InternalError;在 Safari
和 Chrome 中,它是一個 RangeError;在 Internet Explorer中拋出一個通常性的 Error類型。(Opera 不拋出
錯誤;它終止 JavaScript引擎)。這使得咱們可以在 JavaScript 中正確處理這些錯誤:
try {
recurse();
} catch (ex){
alert("Too much recursion!");
}優化
若是無論它,那麼這些錯誤將像其餘錯誤同樣冒泡上傳(在 Firefox中,它結束於 Firebug 和錯誤終端;
在 Safari/Chrome 中它顯示在 JavaScript 終端上),只有 Internet Explorer例外。IE 不會顯示一個 JavaScript
錯誤,可是會彈出一個提示堆棧溢出信息的對話框。
大多數調用棧錯誤與遞歸有關。常見的棧溢出緣由是一個不正確的終止條件,因此定位模式
錯誤的第一步是驗證終止條件。若是終止條件是正確的,那麼算法包含了太多層遞歸,爲了可以安全地在
瀏覽器中運行,應當改用迭代,製表,或二者兼而有之。
任何能夠用遞歸實現的算法均可以用迭代實現。迭代算法一般包括幾個不一樣的循環,分別對應算法過程
的不一樣方面,也會致使本身的性能爲題。可是,使用優化的循環替代長時間運行的遞歸函數能夠提升性能,
由於運行一個循環比反覆調用一個函數的開銷要低。
優化遞歸的方案 製表
一個經典的案例:
function factorial(n){ if (n == 0){ return 1; } else { return n * factorial(n-1); } }
var fact6 = factorial(6); //factorial 計算階乘 var fact5 = factorial(5); var fact4 = factorial(4);
此代碼生成三個階乘結果,factorial()函數總共被調用了 18次。此代碼中最糟糕的部分是,全部必要的
計算已經在第一行代碼中執行過了。由於 6 的階乘等於 6乘以 5 的階乘,因此 5的階乘被計算了兩次。更
糟糕的是,4的階乘被計算了三次。更爲明智的方法是保存並重利用它們的計算結果,而不是每次都從新
計算整個函數。好比這樣:
function memfactorial(n){ if (!memfactorial.cache){ memfactorial.cache = { "0": 1, "1": 1 }; } if (!memfactorial.cache.hasOwnProperty(n)){ memfactorial.cache[n] = n * memfactorial (n-1); } return memfactorial.cache[n]; }
var fact6 = memfactorial(6);
var fact5 = memfactorial(5);
var fact4 = memfactorial(4);
//總共只調用 memfactorial()函數八次
這樣未免太過於繁瑣,若是把製表的過程封裝起來好比這樣:
function memoize(fundamental, cache){ cache = cache || {}; var shell = function(arg){ if (!cache.hasOwnProperty(arg)){ cache[arg] = fundamental(arg); } return cache[arg]; }; return shell; }
//memoize the factorial function var memfactorial = memoize(factorial, { "0": 1, "1": 1 }); //call the new function var fact6 = memfactorial(6); var fact5 = memfactorial(5); var fact4 = memfactorial(4);
須要提醒的是:當一個通用製表函數存在顯著性能問題時,最好在這些函數中人工實現製表法。
最後:運行的代碼總量越大,使用這些策略所帶來的性能提高就越明顯。 代碼全是copy書上的,因此強烈建議直接去看書而不是看我羅裏吧嗦的幾個字總結。
下一章將學習字符串和正則表達式很期待。