讀高性能JavaScript編程 第四章 Conditionals

 if else 和 switch    &&    遞歸  正則表達式

  • 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書上的,因此強烈建議直接去看書而不是看我羅裏吧嗦的幾個字總結。

下一章將學習字符串和正則表達式很期待。

相關文章
相關標籤/搜索