項目上線後,遇見一個很詭異的bug. 不斷有用戶反饋有問題,但開發和測試折騰了好久,都沒找到重現條件。直到有個熱心的用戶跑過來,在用戶的電腦上才發現問題所在:Flash版本過低,在js的某處判斷了flash的版本,之後進入的代碼分支中有這樣一句:
YAHOO.util.Event.on(vipPopup, 'error', function () {...});
vipPopup在此處未定義,因此導致了出錯。一旦找到出錯點,解決起來就快了,不多說。
這問題讓我想起一個一直想總結但一直沒時間去總結的話題:如何讓編寫魯棒的JavaScript代碼?
魯棒(Robust音譯)的定義是:放在正確的環境能得到預期的結果,放在復雜的環境下也不會出錯。很多JavaScript開發者還停留在裸寫代碼的時代,同時業界缺乏便捷低廉的前端測試方案,這導致項目上線後,某些bug在特定環境下才能觸發,結果後續的bug定位就非常麻煩了。如果我們能在開發階段,就讓JavaScript代碼魯棒點,這樣,即便測試覆蓋不到某些分支,也不會因為異常而導致整個js代碼壞掉。下面是我的一些經驗:
一、養成良好的編碼習慣。良好的編碼習慣有兩個來源:一是自己的實踐、摸索和經驗的沉澱,二是他人的經驗,比如閱讀經典書籍,看優秀的代碼。《重構:改善既有代碼的設計》是一本絕好的書,無論是編譯語言還是腳本,我們都應該盡量去除代碼的壞味道,用胃去寫,用鼻子去聞,提升自己的敏覺度。舉一個常見的衛語句使用場景:
就這麼簡單,只要有這個意識,養成了編碼習慣,很自然的就能讓你的代碼更魯棒健壯起來。《重構》等經典好書籍,同樣適合前端開發,不要有畏懼心理,只要我們去琢磨去思考,就能運用到JavaScript程序中來。
好的編碼習慣的培養,還需要多思多想,不斷地從實踐中總結得來。比如構建一些js的基礎類庫,就得非常仔細地考慮暴露的API. 舉個例子:一個方法的返回值是Array, 就得考慮,返回值為空時,應該返回空數組還是null. 大部分情況下,返回空數組是合理的選擇,因為調用處很可能是個循環語句。
或許在不久的將來,我們能看見《Refactoring to JavaScript》這類書籍的問世。當前,多讀一些經典好書,總不會錯的。
二、熟悉所用的框架。無論選擇了哪個框架,抑或公司自己開發了一套框架,在使用時,一定要盡量做到知根知底,這能避免重復造輪子(框架裡有的不必自己再去寫,這一點,看似簡單,要做到還真得費一番苦功夫),能讓代碼精煉優雅。比如上面提到的衛語句,並非任何地方都需要:
YAHOO.util.Event.on(el, 'click', function(ev) { if(!this) return; // do something });
上面的衛語句就是多余的。因為YUI的實現裡,對傳入的參數el已經做了類似判斷,保證el為null或空數組時,不會出錯。
三、換用強勁的IDE輔助開發。EditPlus, EmEditor, Vim等文本編輯器的確很便捷,但當編寫復雜的代碼時,真的不建議繼續用這些編輯器,是時候換成IDE了。看看Java和C#的開發環境吧,代碼提示只是最低級的功能(其實這個有沒有都無所謂),但IDE的重構和即時糾錯等高級功能,對提高代碼的質量是非常有幫助的。比如,如果上面的代碼是用IntelliJ IDEA開發的,則在編寫時就會有提示:
這樣,直接就能將錯誤扼殺在編碼階段。對於Java等編譯型語言來說,這是非常自然的開發過程。對於腳本語言來說,一個好的IDE,也是非常有必要的。保持綠燈常量,一天的心情都會好起來。
養成良好的編碼習慣可以讓我們的代碼更健壯,熟悉所用的框架能讓我們避免不必要的重復代碼,強勁的IDE可以將錯誤直接扼殺在編碼階段。魯棒的JavaScript不是夢,就在你手上。