寫JavaScript時的好習慣(Good Practices)

以下內容是根據讀完”Professional JavaScript for Web Developers 2nd Edition“這本書的心得而來。
  1. 一個function要碼都有return值(在不同condition時),要碼就都沒有。不要有時會return值,有時卻不會。容易造成混洧。
  2. 不要用with statement。因為它會造成執行效能降低。而且會增加debug時的困難。
  3. if – else裡的statement最好都要用括號括起來,即使只有一行。這樣可以增加程式碼的可讀性。
  4. 每行statement最好都要有分號(;)結尾。雖然JavaScript允許每行的結尾可以沒有分號,但這樣之後若要做code壓縮(自動刪除空白和斷行)時,就會產生錯誤了。
  5. 永遠不要用浮點數(floating number)來做compare比較。因為浮點數在JavaScript裡是有誤差值的。
  6. 若要將一個字串(string)變數轉為數字(number)型態時,最好是用parseInt或parseFloat作轉換。若是其他資料型態(data type),則使用Number() casting function。
  7. 透過在function裡的arguments物件,可以模擬類似其他程式語言(如: Java)的多形(Polymorphism)function。在處理時,可以根據傳入不同的參數型態或數量做不同的處理變化。(詳見這篇)
  8. 宣告一個變數時記得前面一定要加var。雖然不加var也是JavaScript可接受的寫法(會變成global variable),但是這樣容易造成混洧和發生錯誤。
  9. 儘量避免明示宣告一個primitive wrapped object(String, Boolean, Number,例: var str = new String(‘test…’);)。因為這會讓開發者搞不清楚他們是在處理reference value or primitive value,容易造成混洧。
  10. 在一個遞迴(recursive)或匿名(anonymous)函式裡,最好使用arguments.callee代替指定function name。這樣一來,日後即使換了function name(reference),也不用跟著調整function code裡面寫到的名稱。
  11. 在使用Closure (a anonymous function inside another function)時,只有在真正需要用到時才用這個寫法,別過度使用它。因為它會保留上層function的整個scope,造成額外的記憶體消耗。
  12. 儘用少用setInterval,因為它有可能會讓一段code還沒結束前就開始執行下一次的程序。可以改用setTimeout加上遞迴(recursive)寫法來達成與setInterval一樣的效果,這樣可保證每次執行code時,上一次程序已經執行結束。
  13. 如果要用JavaScript判斷不同瀏覽器或Capability來做例外處理,最好當成是一般解法無法運作時的最後手段。非不得已才用這個方式。
  14. 不要過度頻繁的操作element的innerText或innerHTML,因為這會降低執行速度,比較沒效率。如果有個迴圈會連續對某個element改寫這兩個properties值,最好先將HTML或文字寫在string buffer裡,然後只做一次改寫的動作。(詳見這篇)
  15. 當使用指定innerHTML來改變一個element時,寫code時最好不要將其element的children綁定event handler。如果element的children已經有綁定event handler,最好手動將綁定的event handler移除掉(例: targetElm.onclick = null;),避免memory leak發生(尤其在IE)。
  16. 儘量減少event handler(function)的數量,因為綁定越多的handler會消耗更多memory,而降低執行效率。可以使用”Event Delegation“的技巧來減少event handler的數量。
  17. 當要寫一段判斷式時(if, while…etc.),最好總是確保括號裡的陳述是一個Boolean值。例如要判斷一個變數是否為一個字串才做處理,最好寫成 if( typeof str == ’string’ ) ,而不要寫成 if( str )。後者雖然也可work(因變數原格式會被自動轉成Boolean格式),但檢查條件鬆散許多,較容易發生不該出現的狀況。
  18. JavaScript與CSS、HTML彼此之間應該儘量減少耦合(coupling)程度。HTML負責提供內容(content),CSS專職呈現(appearance),JavaScript則處理行為(behavior)(詳見這篇)。意即: 在HTML裡不該出現JavaScript及CSS style的code,在JavaScript裡不該去處理CSS style及HTML tag。過度的耦合會造成code maintain上的困難。
  19. 當一段程式邏輯需要耗費大量時間運算時,可以試著將可分割的程式區塊切成數小段,用setTimeout指定一小段時間間隔後再執行。這樣可以讓頁面有更多喘息的時間來回應使用者的操作行為,而有更好的使用者互動經驗。
  20. 將Event Handler裡面的商業邏輯獨立出來。Event Handler應該只處理與Event有關資料,例如抓取keyPress event的keyCode或event target。若要利用這些值做一些處理,則改在別的function裡做。不要pass event object到Event Handler以外的地方。
  21. 儘量減少access global variable的次數可以增進效能,因為減少了traverse time。如果一個function裡有數個地方會access同一個global variable(如: document),可以先用一個local variable去指向global variable,後續的code再access local variable,這樣可加快速度。
  22. 如果要建立一個Storage來存放資料時,用Array會比Object快。在Access資料的速度上,前者的複雜度為O(1),後者為O(n)。
  23. 若一段code有很多if-else時,改採用switch寫法執行速度會比較快一些。另外可以將比較容易match到的case條件排在比較上面,比較少match到的case排在下面,也會讓效能上有些許提昇。
  24. 儘量減少對DOM的操作會使效能有非常顯著的提升,DOM的運算是Browser裡最耗運算資源的。當要對一個HTML element連續插入很多或複雜的child element時,可以用DocumentFragment先將整個DOM結構建立好,再一次加進element,速度會快很多! (詳見這篇)

其他參考:
JSLint – JavaScript Validation Tool
YUI Compressor – JavaScript Compress Tool
Ant – 利用Ant將數個js檔案合併為一個檔案教學

本書作者的Blog: http://www.nczonline.net/