如何編寫高質量代碼


對於開發人員來說,編寫高質量的代碼是有很重要的意義的,特別是在團隊協作里。本篇博文從前端開發的角度,總結出編寫高質量前端代碼的一些經驗。前端開發涉及的主要語言包括html,css,js等。這里主要針對JS來介紹。

 

編碼思維

1. 邏輯思維

當接到某個任務的時候,不要急於開始動手,而是先靜下心來思考,理清這個任務要實現的功能,這個功能用在什么場景下,將來是否會復用,如果將來會變化,可能會怎樣變化。要怎么設計利於功能的擴展和優化,可能會出現哪些問題,如何規避問題。這些都是在前期動筆前需要思考清楚的,不然到后面開發的時候可能會不停的修改,最終效率越來越低。一個功能有着良好的運行邏輯,才不會容易出錯。當然如果時間不允許,或是只上一次就廢棄的功能,此時效率可能會優先考慮。

通常專業的設計師,在設計網頁的時候會使頁面保持相同的風格,相似的模塊同質性很高,這些在我們開發的時候,對復用性較高的代碼定義成公共的模塊或組件。甚至我們在接到設計稿的時候,對於差異較大但是功能類似的頁面提出疑問,提醒視覺保持統一。

有良好的邏輯思維能力和豐富的工作經驗能使我們想的更深更遠。對寫代碼保持強烈的熱情跟好奇心,多看多讀,有些代碼晦澀難懂,比如復雜的算法或是新的概念,沒關系,第一次看了了解,第二次看了就熟悉,第三次可能就精通了,堅持學習和吸收新的知識,有助於我們更好的了解需要開發的功能,磨練自己的邏輯思維,增加解決問題的辦法。

2. 優化思維

對於自己寫過的代碼持懷疑態度,追求完美的代碼。何為完美,每個人的標准不一樣。對於自己寫過的代碼,寫完后想想整個的流程,是否還有值得優化的地方。盡量用最簡潔的代碼來實現,比如用三元運算符代替if語句,重復的代碼提取成方法,重用的功能寫成一個組件等等。對於寫的不好的代碼要有重構的勇氣和信心。

在開發的過程中,還時時需要考慮頁面的性能,選擇性能最好的解決方案。比如JS少用全局變量,用完后及時銷毀,合理使用閉包,避免頻繁操作DOM節點,大量的計算等,HTML代碼的SEO優化,樣式的合理組織等,開發完后通過firebug或chrome自帶的調試工具查看頁面加載的速度,資源大小等,然后有針對性的優化。

3. 設計思維

作為一名前端開發,懂點設計的基礎是很有必要的。前端的設計是指一個畫面或元素,如何在不同的瀏覽器,不同的設備上被創建,顯示,或刪除。我們除了直接跟設計師打交道外,還直接面向用戶,做好響應式的設計與開發,從用戶的角度出發,客觀的評價設計稿所傳達的信息,是否體驗最優,就是我們前端的設計思維。設計的思維,會直接影響我們寫代碼的結構。

 

JS代碼規范

1.前端代碼的組織結構和文件的命名

代碼文件組織結構。前端文件主要包含HTML、CSS、JS等,對於文件組織,既要考慮結構清晰一目了然還要考慮代碼的復用。基於這樣的原則,慣用的做法是同類文件放在一起,並按模塊划分文件結構。比如頁面中公用的組件放到外部公共的components文件夾里,頁面特有的組件則放到該模塊對應的JS文件夾里,每個組件對應有html,js,css等內容。

代碼文件的命名。名稱需要表明文件對應的模塊內容和文件的格式等。使用語義化的名字,避免使用數字來命名,比如a1.html,a2.html等。

2.命名規范

2.1變量

使用合理易於理解的英文變量名稱,變量命名的風格統一,比如都用駝峰命名法,局部變量名盡量簡短。NEJ里的規范,局部變用接口內局部變量或者傳遞的參數用_來量表示,如_type,_index等。對象外可訪問的接口或者屬性,用_$開頭,_$$表示類對象等。

聲明變量必須加上 var 關鍵字.當你沒有寫 var, 變量就會暴露在全局上下文中, 這樣很可能會和現有變量沖突。變量需先聲明后使用,防止變量提升。

另外常量名字都用大寫。

2.2方法

JS面向對象開發中公有接口命名首字母為大寫,私有接口命名首字母小寫。事件的命名用動詞+名詞+動詞的方式,方法名具有語義化,盡量完整。如:onExchange,doExchange,cbExchange等。邏輯操作符 || 和 && 可被用來返回布爾值,簡化代碼。

3.代碼注釋

代碼加上合理的注釋,提高可讀性。例如對於某個功能的簡介,或者變量的特殊含義和用處。每個JS文件頭部說明下作者,日期,文件介紹等。

/**
* KJ-13989 組團買好貨
* author AAA
* 2015-12-09 
*/
/**
 * 接口函數的說明
 * 參數說明
 */
/**
  * 空閑控制 返回函數連續調用時,空閑時間必須大於或等於 wait,func 才會執行
  *
  * @param {function} func    傳入函數
  * @param {number}  wait    表示時間窗口的間隔
  * @param {boolean} immediate  設置為ture時,調用觸發於開始邊界而不是結束邊界
  * @return {function}       返回客戶調用函數
  */

當你寫注釋時一定要注意:不要寫你的代碼都干了些什么,而要寫你的代碼為什么要這么寫,背后的考量是什么。對於文件的修改,也可以在注釋里加上相關的任務號。

4.語句結束時添加分號

記得語句結束時使用分號。如果僅依靠語句間的隱式分隔, 有時會很麻煩。而且添加分號也利於代碼的理解。

5.不要在塊內聲明一個函數,使用函數表達式來定義函數

不要寫成:

if (x) {
  function foo() {}
}

雖然很多 JS 引擎都支持塊內聲明函數, 但它不屬於 ECMAScript 規范 (見 ECMA-262, 第13和14條)。 各個瀏覽器的實現相互不兼容, 有些也與未來 ECMAScript 草案相違背。ECMAScript 只允許在腳本的根語句或函數中聲明函數。 如果確實需要在塊中定義函數, 建議使用函數表達式來初始化變量:

if (x) {
  var foo = function() {}
}

6.避免定義全局變量或函數

函數可以采用匿名函數包裹的方法實現封裝,如

(function(){
    //do some thing
})()

全局變量可以通過定義全局對象變量來存儲,像在ftl頁面的JS中定義ftl值的時候,可以統一寫成:

var configInfos ={
        remindType:${remindType!2},
        totalPoint:${pointTotalCount!0},
        isSigned:"${isSigned?string('yes','no')}"
    }

而后通過configInfos.remindType獲取到remindType值。這樣可以減少全局變量的個數,避免變量沖突。

7.使用單引號定義字符串。

ftl文件中用雙引號,JS中用單引號。

8.使用簡化的編碼方式。

如對象和數組的聲明,三元操作符等。

var a = [],obj={};

9.避免使用with語句。

該語句在設計上就有缺陷,在ES5和ES6上也存在潛在兼容問題。對性能也有很大影響。

10.避免使用eval。

存在潛在安全問題,在需要使用eval的場景中應當盡量使用其它方法代替。

11.事件處理和業務邏輯分離,數據和代碼邏輯分離。

現在使用的RegularJs框架正是實現了數據與代碼邏輯的分離。

12.結構樣式與邏輯分離

CSS樣式分離,將多個樣式放置在class中后控制class的增刪,通過掛靠樣式名來改變樣式。避免在JS中對元素操作大量的style來改變樣式。

_e._$addClassName(this.__passWord,'u-ipt-login-active');

13.合理定義交互元素的樣式名

在JS中,可以通過獲取元素的className,id,或元素名來操作DOM節點。如果是頁面上固定的節點,則可以通過給元素掛靠'ztag','j-flag'等樣式名。這些名字不需要帶任何樣式。避免用大量的id來獲取元素。如果是通過判斷來顯示的元素,則可以通過ID來獲取。

pro.__getNodes = function(){
        var _node = _e._$getByClassName(document.body,'ztag'),i=0;
        this.__aboutWrap = _node[i++];
        this.__goodsDescWrap = _node[i++];
        this.__fixedBtn = _node[i++];
        this.__payBtn = _node[i++];
    };

14.代碼格式化

15.理解 JavaScript 的定義域和定義域提升,提前聲明變量

在 JavaScript 中變量和方法定義會自動提升到執行之前。JavaScript 只有 function 級的定義域,而無其他很多編程語言中的塊定義域,所以使得你在某一function 內的某語句和循環體中定義了一個變量,此變量可作用於整個 function 內,而不僅僅是在此語句或循環體中,因為它們的聲明被 JavaScript 自動提升了。所以一般在函數開頭先聲明好變量。避免變量在定義前被使用,導致報錯。

16.合理使用AJAX技術

明確AJAX技術的使用場景,在AJAX過程中做好用戶的交互,如禁用按鈕避免重復觸發、顯示加載進度條等。

17.內存回收

全局對象或對象的屬性使用完后,將值設為null或undefined,或者某個實例化的組件,使用后及時解除引用(recycle或destroy方法),解除已經不需要的事件監聽(delEvent),不要在函數內返回外部不需要的對象等。這些操作利於瀏覽器的回收程序執行時能回收其占用的內存。

18.使用高性能的變量或屬性值的讀取方式

在使用變量和屬性時,如果需要多次調用,則定義成局部變量再使用。最簡單的例如for循環中,可以將變量或屬性緩存起來:

for(var i=0,len=number.length;i<len;i++){}

變量涉及作用域鏈查找的過程,屬性涉及原型鏈查找的過程,定義成局部變量可以節約查找的時間。

19.高效的DOM操作

DOM操作對性能最大的影響是因為它導致了瀏覽器的重排和重繪。

使用文檔片段:創建一個文檔片段(documentFragment),並在此片段上進行DOM操作,操作完成后將它附加在頁面中,這樣重排和重繪的操作就只有附加了。

通過設置DOM元素額的display樣式為none來隱藏元素:通過隱藏DOM達到在頁面中移除元素的效果,這樣重排和重繪的操作就只有隱藏和顯示了。

克隆DOM元素到內存中:將元素克隆一份然后在內存中操作DOM,操作完之后替換,這樣重排和重繪的操作就只有替換了。當元素中有事件綁定時,cloneNode會把事件移除掉,不適合用這種方法來操作。

設置具有動畫效果的DOM元素的position為fixed或absolute:使元素脫離頁面布局流,從而避免頁面頻繁的重排。

謹慎取得DOM元素的布局信息(offsetHeight等):如果需要重復使用這些信息可以先緩存起來。

使用事件委托來綁定事件:利用事件冒泡機制,只在父元素上綁定事件,然后在事件處理函數中根據傳入的參數判斷事件的源元素,然后針對不同的源元素做不同的處理。這樣避免了給多個子元素綁定事件。

20.增加容錯處理

例如給變量或屬性設置默認值,對某段代碼使用try,catch操作。

21.代碼注意安全性

常見的Web前端攻擊方式有XSS Cross Site Scripting 跨站點腳本攻擊,CSRF Cross Site Request Forgery 跨站請求偽造,界面操作劫持等。我們需要注意的是不輕信任何用戶輸入的內容,針對用戶輸入的內容進行HTML編碼、JavaScript編碼、CSS編碼、URL編碼等。對用戶表單提交的數據做完整的驗證。

22.移動端開發注意點

使用流式布局。使用合適的圖片顯示兼容方案。使用移動平台特有事件處理如手勢操作。增加鏈接按鈕的可操作區域,如安卓開發規范中保證這些控件的高度至少有48px間隔至少有32px等。

23.代碼檢查,code review

24.ftl里代碼優化

ftl里避免在JS中填充大量的數據,尤其是像列表數據,不利於優化。如果確實需要,在JS獲得數據后刪除該節點。

 

其他注意點

1.提前設計

提前規划設計好,從全局角度規划代碼的結構。保證代碼精簡,寫完某個功能后重新思考下整個流程,是否可以優化,方向有沒有寫錯。

我記得剛開始寫代碼的時候,某個功能寫到某一步的時候,發現寫不下去了,這個時候只能重新換個思路,推倒之前的代碼重新寫。這就是沒有提前規划好思路,急於下筆,導致浪費了很多時間。

2.前端代碼重構注意事項

重構前一定要預估風險,如果沒有足夠的自動化測試,最好是先完善自動化測試代碼。

重構的目的和范圍要明確,切忌盲目修改,前端代碼的重構目的主要是提高代碼的可維護性、可讀性和性能。

最好是先易后難,循序漸進。首先修改諸如命名、格式等不涉及具體邏輯的內容,然后考慮模塊化和性能提升等具體邏輯相關的內容。

重構過程中要持續測試,在多個瀏覽器中測試,確保重構一部分功能正確,切忌在大量重構后再進行測試,因為大量重構后基本很難記得重構的邏輯,也就有可能遺漏部分測試用例。

如果是提升性能,要事先檢測網站的整體性能並量化,找出性能瓶頸,重構過程中要持續監控性能,並對比性能提升的效果。

3.快速編寫頁面

拿到設計稿后,規划好結構,先寫完html代碼,最后再補充完整的樣式,這樣效率最高。邊寫邊調是很浪費時間的。

 

參考文章:

http://itwap.net/ArticleContent.aspx?id=35

http://www.css88.com/archives/5366


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM