1. 保證代碼壓縮后不出錯
對于大型的JavaScript項目,一般會在產(chǎn)品發(fā)布時對項目包含的所有JavaScript文件進行壓縮處理,比如可以利用Google Closure Compiler Service對代碼進行壓縮,新版jQuery已改用這一工具對代碼進行壓縮,這一般會去掉開發(fā)時寫的注釋,除去所有空格和換行,甚至可以把原來較長的變量名替換成短且無意義的變量名,這樣做的目的是加快文件的下載速度,同時也減小網(wǎng)站訪問帶來的額外數(shù)據(jù)流量,另外在代碼保護上也起到了一點點作用,至少壓縮后的代碼即使被還原還是沒那么容易一下讀懂的。要想代碼能正確通過壓縮,一般要求語句都要以分號正常結(jié)束,大括號也要嚴(yán)格結(jié)束等,具體還要看壓縮工具的要求。所以如果一開始沒有按標(biāo)準(zhǔn)來做,等壓縮出錯后再回去找錯誤那是浪費時間。
2. 保證代碼能通過特定IDE的自動格式化功能
一般較為完善的開發(fā)工具(比如Aptana Studio)都有代碼"自動格式"化功能,這一功能幫助實現(xiàn)統(tǒng)一換行、縮進、空格等代碼編排,你可以設(shè)置自己喜歡的格式標(biāo)準(zhǔn),比如左大括號{是否另起一行。達到這個要求的目的在于方便你的開發(fā)團隊成員拿你代碼的一個副本用IDE自動格式化成他喜歡或熟悉的風(fēng)格進行閱讀。你同事需要閱讀你的代碼,可能是因為你寫的是通用方法,他在其它模塊開發(fā)過程中也要使用到,閱讀你的代碼能最深入了解方法調(diào)用和實現(xiàn)的細節(jié),這是簡單API文檔不能達到的效果。
3. 使用標(biāo)準(zhǔn)的文檔注釋
這一要求算是最基本的,這有利于在方法調(diào)用處看到方法的具體傳參提示,也可以利用配套文檔工具生成html或其它格式的開發(fā)文檔供其他團隊成員閱讀,你可以嘗試使用jsdoc-toolkit。如果你自動生成的API是出自一個開放平臺,就像facebook.com應(yīng)用,那么你的文檔是給天下所有開發(fā)者看的。另外編寫完整注釋,也更方便團隊成員閱讀你的代碼,通過你的參數(shù)描述,團隊成員可以很容易知道你編寫的方法傳參與實現(xiàn)細節(jié)。當(dāng)然也方便日后代碼維護,這樣即使再大的項目,過了很長時間后,回去改點東西也就不至于自己都忘記了當(dāng)時自己寫的代碼是怎么一回事了。
4. 使用規(guī)范有意義的變量名
使用規(guī)范有意義的變量名可以提高代碼的可讀性,作為大項目開發(fā)成員,自己寫的代碼不僅僅要讓別人容易看懂。開發(fā)大項目,其實每個人寫的代碼量可能都比較大,規(guī)范命名,日后自己看回自己的代碼也顯的清晰易懂,比如日后系統(tǒng)升級或新增功能,修改起代碼來也輕松多了。如果到頭發(fā)現(xiàn)自己當(dāng)初寫的代碼現(xiàn)在看不太懂了,那還真是天大的笑話了。
當(dāng)然,使用有意義的變量名也盡量使用標(biāo)準(zhǔn)的命名,比如像這里:var me = this也許沒有var self = this好,因為self是Python中的關(guān)鍵字,在Python中self就是通常語言this的用法。再看下面一個例子,加s顯然比沒有加來的科學(xué)些,這樣可以知道這個變量名存的是復(fù)數(shù),可能是數(shù)組等:
var li = document.getElementsByTagName('li') var lis = document.getElementsByTagName('li')
5. 不使用生偏語法
JavaScript作為一門動態(tài)腳本語言,靈活性既是優(yōu)點也是缺點,眾所周知,動態(tài)語言不同層次開發(fā)人員對實現(xiàn)同樣一個功能寫出來的代碼在規(guī)范或語法上會存在較大的差別。不管怎么樣,規(guī)范編碼少搞怪,不把簡單問題復(fù)雜化,不違反代碼易讀性原則才是大家應(yīng)該做的。
比如這語句:typeof(b) == 'string' && alert(b)應(yīng)該改為:if (typeof(b) == 'string') alert(b),像前面那種用法,利用了&&運算符解析機制:如果檢測到&&前語句返回false就不再檢測后面語句,在代碼優(yōu)化方面也有提到把最可能出現(xiàn)的情況首先判斷,像這種寫法如果條件少還好,如果條件較多而且語句也長,那代碼可讀性就相當(dāng)差。
又比如:+function(a){var p = a;}( 'a')應(yīng)該改為:(function(a){var p = a;})( 'a'),其實function前面的+號與包含function的()括號作用是一樣的,都是起運算優(yōu)先作用,后者是常見且容易看明白的防止變量污染的做法,比如好些流行JavaScript框架就是采用后面這種方式。
再說個降低代碼可讀性的例子,如:function getPostionTxt(type){return type == 2 ? "野外" : (type == 3 ? "商城" : (type == 4 ? "副本" : null));}應(yīng)該改成:function getPostionTxt(type){var typeData={"2":"野外","3":"商城","4":"副本"};if (typeData[type]) return typeData[type]; else return null;}。如果type是從0開始不間斷的整數(shù),那么直接使用數(shù)組還更簡單,這種結(jié)果看起來就清晰多了,看到前面那種多層三元表達式嵌套頭不暈嗎。
6. 不在語句非賦值地方出生中文
語句中不應(yīng)該出現(xiàn)中文我想一般人都知道,雖然這樣做不影響程序運行,但是顯然有背行業(yè)標(biāo)準(zhǔn)要求,當(dāng)然我們也不是在使用"易語言"做開發(fā)。關(guān)于這一個問題,我本來不想把它拿出來說的,但我確實遇到有人這樣做的,也不知道是不是因為他的英語實在太爛了,至少還可以用拼音吧,另外尋求翻譯工具幫忙也不錯的選擇。我舉例如下,像以下寫法出現(xiàn)在教學(xué)中倒還可以理解:
this.user['名字'] = '張三' 或者 this.user.名字 = '張三'
7. 明確定義函數(shù)固定數(shù)量的參數(shù)
固定數(shù)量參數(shù)的函數(shù)內(nèi)部不使用arguments去獲取參數(shù),因為這樣,你定義的方法如果包含較多的腳本,就不能一眼看到這個方法接受些什么參數(shù)以及參數(shù)的個數(shù)是多少。比如像下面:
var $ = function(){return document.getElementById(arguments[0]);}應(yīng)該改成:var $ = function(elemID){return document.getElementById(elemID);}
8. 不必?zé)嶂詣討B(tài)事件綁定
雖然知道事件可以動態(tài)綁定,比如使用addEventListener或者使用jQuery的bind方法,也知道采用動態(tài)事件綁定可以讓XHTML更干凈,但是一般情況下我還是建議直接把事件寫在DOM節(jié)點上,我認為這樣可以使代碼變得更容易維護,因為這樣做,我們在查看源代碼的時候就可以容易地知道什么Element綁定了什么方法,簡單說這樣更容易知道一個按鈕或鏈接點擊時調(diào)了什么方法腳本。
9. 降低代碼與XHTML的耦合性
不要過于依賴DOM的一些內(nèi)容特征來調(diào)用不同的腳本代碼,而應(yīng)該定義不同功能的方法,然后在DOM上調(diào)用,這樣不管DOM是按鈕還是鏈接,方法的調(diào)用都是一樣的,比如像下面的實現(xiàn)顯然會存在問題:
function myBtnClick(obj) { if (/確定/.test(obj.innerHTML)) alert('OK'); else if (/取消/.test(obj.innerHTML)) alert('Cancel'); else alert('Other'); } <a herf="javascript:;" onclick="myBtnClick(this)">確定</a><a herf="javascript:;" onclick="myBtnClick(this)">取消</a>
上面例子其實在一個函數(shù)內(nèi)處理了兩件事情,應(yīng)該分成兩個函數(shù),像上面的寫法,如果把鏈接換成按鈕,比如改成這樣:<input type="button" onclick="myBtnClick(this)" value="確定" />,那么myBtnClick函數(shù)內(nèi)部的obj.innerHTML就出問題了,因為此時應(yīng)該obj.value才對,另外如果把按鈕名稱由中文改為英文也會出問題,所以這種做法問題太多了。
10. 一個函數(shù)應(yīng)該返回統(tǒng)一的數(shù)據(jù)類型
因為JavaScrip是弱類型的,在編寫函數(shù)的時候有些人對于返回類型的處理顯得比較隨便,我覺得應(yīng)該像強類型語言那樣返回,看看下面的兩個例子:
function getUserName(userID) { if (data[userID]) return data[userID]; else return false; } 應(yīng)該改為: function getUserName(userID) { if (data[userID]) return data[userID]; else return ""; }
這個方法如果在C#中定義,我們知道它準(zhǔn)備返回的數(shù)據(jù)類型應(yīng)該是字符串,所以如果沒有找到這個數(shù)據(jù)我們就應(yīng)該返回空的字符串,而不是返回布爾值或其它不合適的類型。這并沒有影響到函數(shù)將來的調(diào)用,因為返回的空字符串在邏輯判斷上可被認作"非",即與false一樣,除非我們使用全等于"==="或typeof進行判斷。
11. 規(guī)范定義JSON對象,補全雙引號
使用標(biāo)準(zhǔn)肯定是有好處的,那么為什么還是有人不使用標(biāo)準(zhǔn)呢?我想這可能是懶或習(xí)慣問題。也許還會有人跟我說,少寫引號可以減輕文件體積,我認為這有道理但不是重點。對于服務(wù)器返回的JSON數(shù)據(jù),使用標(biāo)準(zhǔn)結(jié)構(gòu)可以利用Firefox瀏覽器的JSONView插件方便查看(像查看XML那樣樹形顯示),另外你如果使用jQuery做開發(fā),最新版本jQuery1.4+是對JSON格式有更高要求的,具體的可以自己查閱jQuery更新文檔。比如:{name:"Tom"}或{'name':'Tom'}都應(yīng)該改成{"name":"Tom"}。
12. 不在文件中留下未來確定不再使用的代碼片段
當(dāng)代碼調(diào)整或重構(gòu)后,之前編寫的不再使用的代碼應(yīng)該及時刪除,如果認為這些代碼還有一定利用價值可以把它們剪切到臨時文件中。留在項目中不僅增加了文件體積,這對團隊其它成員甚至自己都起到一定干擾作用,怕將來自己看回代碼都搞不懂這方法是干什么的,是否有使用過。當(dāng)然可以用文檔注釋標(biāo)簽@deprecated把這個方法標(biāo)識為不推薦的。
13. 不重復(fù)定義其他團隊成員已經(jīng)實現(xiàn)的方法
對于大型項目,一般會有部分開發(fā)成員實現(xiàn)一些通用方法,而另外一些開發(fā)成員則要去熟悉這些通用方法,然后在自己編寫模塊遇到有調(diào)用的需要就直接調(diào)用,而不是像有些開發(fā)者喜歡"單干",根本不會閱讀這些通用方法文檔,在自己代碼中又寫了一遍實現(xiàn),這不僅產(chǎn)生多余的代碼量,當(dāng)然也是會影響團隊開發(fā)效率的,這是沒有團隊合作精神的表現(xiàn),是重復(fù)造輪子的悲劇。
比如在通用類文件Common.js有定義function $(elemID){return document.getElementById(elemID)}那么就不應(yīng)該在Mail.js中再次出現(xiàn)這一功能函數(shù)的重復(fù)定義,對于一些復(fù)雜的方法更應(yīng)該如此。
14. 調(diào)用合適的方法
當(dāng)有幾個方法都可以實現(xiàn)同類功能的時候,我們還是要根據(jù)場景選擇使用最合適的方法。下面拿jQuery框架的兩個AJAX方法來說明。如果確定服務(wù)器返回的數(shù)據(jù)是JSON應(yīng)該直接使用$.getJSON,而不是使用$.get得到數(shù)據(jù)再用eval函數(shù)轉(zhuǎn)成JSON對象。如果因為本次請求要傳輸大量的數(shù)據(jù)而不得以使用$.post也應(yīng)該采用指定返回數(shù)據(jù)類型(設(shè)置dataType參數(shù))的做法。如果使用$.getJSON,在代碼中我們一眼能看出本次請求服務(wù)器返回的是JSON。
溫馨提示:jQuery1.4后,如果服務(wù)器有設(shè)置數(shù)據(jù)輸出的ContentType,比如ASP.NET C#設(shè)置 Response.ContentType = "application/json",那么$.get將與$.getJSON的使用沒有什么區(qū)別。
15. 使用合適的控件存儲合適的數(shù)據(jù)
曾發(fā)現(xiàn)有人利用DIV來保存JSON數(shù)據(jù),以待頁面下載后將來使用,像這樣:<div id="json">{ "name":"Tom"}</div>,顯然這個DIV不是用來界面顯示的,如果非要這樣做,達到使用HTML文件進行數(shù)據(jù)緩存的作用,至少改成用隱藏域來存這數(shù)據(jù)更合理,比如改成:<input type="hidden" value=" { "name":"Tom"}" />。
其實也可以利用window對象來保存一些數(shù)據(jù),像上面的例子,我們可以在AJAX請求頁直接包含這樣的腳本塊:<script>window.userData = { "name":"Tom"};</script>,當(dāng)在AJAX請求回調(diào)函數(shù)中執(zhí)行完$( "#MyDiv ").html(data)后,在window上就馬上有了這一變量。如果采用第一種方法,將不可避免eval(document.getElementById("UserData").innerHTML)。如果在window對象存放大量數(shù)據(jù)的話,這些數(shù)據(jù)不用時要及時手動清理它們,它們是要等瀏覽器刷新或重啟后才會消失的,這就會增加內(nèi)存開銷。
16. 永遠不要忽略代碼優(yōu)化工作
代碼最優(yōu)化是每個程序員應(yīng)該努力達到的目標(biāo),也應(yīng)該成為程序員永遠的追求。寫代碼的時候,不應(yīng)該急著把功能實現(xiàn)出來,要想一下如何寫代碼,代碼的執(zhí)行效率才是較好的。
舉個例子:假設(shè)有定義getElementById的快捷方法functoin $(elemID){return document.getElementById(elemID)},那么有人可能會寫出這樣的代碼$("MyDiv").parentNode.removeChild($("MyDiv")),其實這里執(zhí)行了兩次getElementById DOM查找,如果改成這樣將更好:var myDiv = $("MyDiv"); myDiv.parentNode.removeChild(myDiv)。還好getElementById的DOM查找算比較快,如果換成getElementsByTagName則更應(yīng)該注重優(yōu)化了。jQuery開發(fā)團隊也有提醒大家要注意這方面的問題。
當(dāng)然,代碼優(yōu)化技巧也是需要個人不斷積累的。曾有朋友跟我說他寫網(wǎng)站后臺代碼從來不用考慮優(yōu)化的,因為他們網(wǎng)站用的是至強四核服務(wù)器,我覺得這是很可笑的。
17. 會分析策劃文檔,能用面向?qū)ο蠓椒ㄟM行接口定義和代碼組織
這一能力對于每一個程序員來說都是非常重要的,這也是決定一個程序員水平高低的一個重要因素。能夠把需求細化并抽象出不同的類,然后有條理地編寫代碼,使代碼結(jié)構(gòu)清晰,可讀性高,代碼易于維護,不至于太過程化而且雜亂無章,這樣才算是一個優(yōu)秀的程序員。
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com