在學習編程的時候,每次看到那些整齊規范的代碼,心里頓時對這個程序員表示點點好感,有時,比如看到自己和朋友寫的代碼時,那閱讀起來就是苦不堪言,所以,一些基本的開發規范是必須的,是為了自己方便閱讀代碼,也方便他人閱讀修改代碼。
命名
駝峰式命名法介紹
Pascal Case 大駝峰式命名法:首字母大寫。eg:StudentInfo、UserInfo、ProductInfo
Camel Case 小駝峰式命名法:首字母小寫。eg:studentInfo、userInfo、productInfo
文件資源命名
文件名不得含有空格
文件名建議只使用小寫字母,不使用大寫字母。( 為了醒目,某些說明文件的文件名,可以使用大寫字母,比如README、LICENSE。 )
文件名包含多個單詞時,單詞之間建議使用半角的連詞線 ( - ) 分隔。
引入資源使用相對路徑,不要指定資源所帶的具體協議 ( http:,https: ) ,除非這兩者協議都不可用。
推薦:
<script src="//cdn.com/foundation.min.js"></script>
- 1
變量命名
命名方式: 小駝峰式命名方法
命名規范: 類型+對象描述的方式,如果沒有明確的類型,就可以使前綴為名詞
類型 小寫字母
array a
boolean b
function fn
int i
object o
regular r
string s
函數
命名方式:小駝峰方式 ( 構造函數使用大駝峰命名法 )
命名規則:前綴為動詞
動詞 含義 返回值
can 判斷是否可執行某個動作 ( 權限 ) 函數返回一個布爾值。true:可執行;false:不可執行
has 判斷是否含有某個值 函數返回一個布爾值。true:含有此值;false:不含有此值
is 判斷是否為某個值 函數返回一個布爾值。true:為某個值;false:不為某個值
get 獲取某個值 函數返回一個非布爾值
set 設置某個值 無返回值、返回是否設置成功或者返回鏈式對象
推薦:
//是否可閱讀 function canRead(){ return true; } //獲取姓名 function getName{ return this.name }
常量
命名方法:全部大寫
命名規范:使用大寫字母和下划線來組合命名,下划線用以分割單詞
推薦:
var MAX_COUNT = 10; var URL = 'http://www.baidu.com';
- 1
- 2
類的成員
- 公共屬性和方法:同變量命名方式
- 私有屬性和方法:前綴為下划線(_)后面跟公共屬性和方法一樣的命名方式
推薦(將name換成this是不是更熟悉了呢)
function Student(name) { var _name = name; // 私有成員 // 公共方法 this.getName = function () { return _name; } // 公共方式 this.setName = function (value) { _name = value; } } var st = new Student('tom'); st.setName('jerry'); console.log(st.getName()); // => jerry:輸出_name私有變量的值
注釋規范
單行注釋(//)
- 單獨一行://(雙斜線)與注釋文字之間保留一個空格
- 在代碼后面添加注釋://(雙斜線)與代碼之間保留一個空格,並且//(雙斜線)與注釋文字之間保留一個空格。
-
注釋代碼://(雙斜線)與代碼之間保留一個空格。
推薦:
// 調用了一個函數;1)單獨在一行 setTitle(); var maxCount = 10; // 設置最大量;2)在代碼后面注釋 // setName(); // 3)注釋代碼
多行注釋( / 注釋說明 /)
- 若開始(/和結束(/)都在一行,推薦采用單行注釋
- 若至少三行注釋時,第一行為/,最后行為/,其他行以開始,並且注釋文字與保留一個空格。
推薦:
/*
* 代碼執行到這里后會調用setTitle()函數 * setTitle():設置title的值 */ setTitle();
函數(方法)注釋
函數(方法)注釋也是多行注釋的一種,但是包含了特殊的注釋要求,參照 javadoc(百度百科)
語法:
/** * 函數說明 * @關鍵字 */
常用注釋關鍵字
注釋名 語法 含義 示例
@param @param 參數名 {參數類型} 描述信息 描述參數的信息 @param name {String} 傳入名稱 @return @return {返回類型} 描述信息 描述返回值的信息 @return {Boolean} true:可執行;false:不可執行 @author @author 作者信息 [附屬信息:如郵箱、日期] 描述此函數作者的信息 @author 張三 2015/07/21 @version @version XX.XX.XX 描述此函數的版本號 @version 1.0.3 @example @example 示例代碼 @example setTitle('測試') 如下
推薦:
/** - 合並Grid的行 - @param grid {Ext.Grid.Panel} 需要合並的Grid - @param cols {Array} 需要合並列的Index(序號)數組;從0開始計數,序號也包含。 - @param isAllSome {Boolean} :是否2個tr的cols必須完成一樣才能進行合並。true:完成一樣;false(默認):不完全一樣 - @return void - @author polk6 2015/07/21 - @example - _________________ _________________ - | 年齡 | 姓名 | | 年齡 | 姓名 | - ----------------- mergeCells(grid,[0]) ----------------- - | 18 | 張三 | => | | 張三 | - ----------------- - 18 --------- - | 18 | 王五 | | | 王五 | - ----------------- ----------------- */ function mergeCells(grid, cols, isAllSome) { // Do Something }
HTML規范
文檔規范
HTML5的文檔類型聲明:<!DOCTYPE html>
- DOCTYPE標簽是一種標准通用標記語言的文檔類型聲明,它的目的是要告訴標准通用標記語言解析器,它應該使用什么樣的文檔類型定義(DTD)來解析文檔。
- 使用文檔聲明類型的作用是為了防止開啟瀏覽器的怪異模式。
- 沒有DOCTYPE文檔類型聲明會開啟瀏覽器的怪異模式,瀏覽器會按照自己的解析方式渲染頁面,在不同的瀏覽器下面會有不同的樣式。
- 如果你的頁面添加了
腳本加載
推薦:
<html> <head> <link rel="stylesheet" href="main.css"> </head> <body> <!-- body goes here --> <script src="main.js" async></script> </body> </html>
只兼容現代瀏覽器推薦:
<html> <head> <link rel="stylesheet" href="main.css"> <script src="main.js" async></script> </head> <body> <!-- body goes here --> </body> </html>
語義化
語義化是指:根據元素其被創造出來時的初始意義來使用它。
意思就是用正確的標簽干正確的事,而不是只有div和span。
- 1
- 2
推薦:
html 代碼:
<!-- The page header should go into a header element --> <header> <!-- As this title belongs to the page structure it's a heading and h1 should be used --> <h1>My page title</h1> </header> <!-- All navigation should go into a nav element --> <nav class="top-navigation"> <!-- A listing of elements should always go to UL (OL for ordered listings) --> <ul> <li class="nav-item"><a href="#home">Home</a></li> <li class="nav-item"><a href="#news">News</a></li> <li class="nav-item"><a href="#about">About</a></li> </ul> </nav> <!-- The main part of the page should go into a main element (also use role="main" for accessibility) --> <main class="news-page" role="main"> <!-- A section of a page should go into a section element. Divide a page into sections with semantic elements. --> <section class="page-section news"> <!-- A section header should go into a section element --> <header> <!-- As a page section belongs to the page structure heading elements should be used (in this case h2) --> <h2 class="title">All news articles</h2> </header> <!-- If a section / module can be seen as an article (news article, blog entry, products teaser, any other re-usable module / section that can occur multiple times on a page) a article element should be used --> <article class="news-article"> <!-- An article can contain a header that contains the summary / introduction information of the article --> <header> <!-- As a article title does not belong to the overall page structure there should not be any heading tag! --> <div class="article-title">Good article</div> <!-- Small can optionally be used to reduce importance --> <small class="intro">Introduction sub-title</small> </header> <!-- For the main content in a section or article there is no semantic element --> <div class="content"> <p>This is a good example for HTML semantics</p> </div> <!-- For content that is represented as side note or less important information in a given context use aside --> <aside class="article-side-notes"> <p>I think I'm more on the side and should not receive the main credits</p> </aside> <!-- Articles can also contain footers. If you have footnotes for an article place them into a footer element --> <footer class="article-foot-notes"> <!-- The time element can be used to annotate a timestamp. Use the datetime attribute to specify ISO time while the actual text in the time element can also be more human readable / relative --> <p>This article was created by David <time datetime="2014-01-01 00:00" class="time">1 month ago</time></p> </footer> </article> <!-- In a section, footnotes or similar information can also go into a footer element --> <footer class="section-footer"> <p>Related sections: Events, Public holidays</p> </footer> </section> </main> <!-- Your page footer should go into a global footer element --> <footer class="page-footer"> Copyright 2014 </footer>
alt標簽不為空
標簽的 alt 屬性指定了替代文本,用於在圖像無法顯示或者用戶禁用圖像顯示時,代替圖像顯示在瀏覽器中的內容。
假設由於下列原因用戶無法查看圖像,alt 屬性可以為圖像提供替代的信息:
- 網速太慢
- src屬性中的錯誤
- 瀏覽器禁用圖像
- 用戶使用的是屏幕閱讀器
結構、表現、行為三者分離
盡量在文檔和模板中只包含結構性的 HTML;而將所有表現代碼,移入樣式表中;將所有動作行為,移入腳本之中。
在此之外,為使得它們之間的聯系盡可能的小,在文檔和模板中也盡量少地引入樣式和腳本文件。
建議:
- 不使用超過一到兩張樣式表
- 不使用超過一到兩個腳本(學會用合並腳本)
- 不使用行內樣式()
- 不在元素上使用 style 屬性(
) - 不使用行內腳本()
- 不使用表象元素(i.e. , ,
, , ) - 不使用表象 class 名(i.e. red, left, center)
HTML只關注內容
- HTML只顯示展示內容信息
- 不要引入一些特定的 HTML 結構來解決一些視覺設計問題
- 不要將img元素當做專門用來做視覺設計的元素
- 樣式上的問題應該使用css解決
推薦:
html 代碼:
<!-- That's clean markup! --> <span class="text-box"> See the square next to me? </span> css 代碼: /* We use a :before pseudo element to solve the design problem of placing a colored square in front of the text content */ .text-box:before { content: ""; display: inline-block; width: 1rem; height: 1rem; background-color: red; }
圖片和 SVG 圖形能被引入到 HTML 中的唯一理由是它們呈現出了與內容相關的一些信息。
推薦:
html 代碼:
<!-- That's clean markup! --> <span class="text-box"> See the square next to me? </span> css 代碼: /* We use a :before pseudo element with a background image to solve the problem */ .text-box:before { content: ""; display: inline-block; width: 1rem; height: 1rem; background: url(square.svg) no-repeat; background-size: 100%; }
js規范
避免全局命名空間污染
防止全局命名空間被污染,我們通常的做法是將代碼包裹成一個 IIFE(Immediately-Invoked Function Expression),創建獨立隔絕的定義域。也使得內存在執行完后立即釋放。
IIFE 還可確保你的代碼不會輕易被其它全局命名空間里的代碼所修改(i.e. 第三方庫,window 引用,被覆蓋的未定義的關鍵字等等)。
推薦:
// We declare a IIFE and pass parameters into the function that we will use from the global space (function(log, w, undefined){ 'use strict'; var x = 10, y = 100; // Will output 'true true' log((w.x === undefined) + ' ' + (w.y === undefined)); }(window.console.log, window));
'use strict'; // Code goes here }());
如果你想引用全局變量或者是外層 IIFE 的變量,可以通過下列方式傳參:
(function($, w, d){ 'use strict'; $(function() { w.alert(d.querySelectorAll('div').length); }); }(jQuery, window, document));
嚴格模式
ECMAScript 5 嚴格模式可在整個腳本或獨個方法內被激活。它對應不同的 javascript 語境會做更加嚴格的錯誤檢查。嚴格模式也確保了 javascript 代碼更加的健壯,運行的也更加快速。
嚴格模式會阻止使用在未來很可能被引入的預留關鍵字。
你應該在你的腳本中啟用嚴格模式,最好是在獨立的 IIFE 中應用它。避免在你的腳本第一行使用它而導致你的所有腳本都啟動了嚴格模式,這有可能會引發一些第三方類庫的問題。
變量聲明
總是使用 var 來聲明變量,並且使用單var模式(將所有的變量在函數最前面只使用一個var定義)。例如:
(function (){ 'use strict' var a = 0, b = 0, c = 0, i, j, myObject(); }())
js聲明提前
javascript會自動將函數作用域內的變量和方法的定義提前(只是提前聲明,賦值還是在原處)
例如:
(function(log){ 'use strict'; var a = 10; for(var i = 0; i < a; i++) { var b = i * i; log(b); } if(a === 10) { var f = function() { log(a); }; f(); } function x() { log('Mr. X!'); } x(); }(window.console.log));
提升后的js
(function(log){ 'use strict'; // All variables used in the closure will be hoisted to the top of the function var a, i, b, f; // All functions in the closure will be hoisted to the top function x() { log('Mr. X!'); } a = 10; for(i = 0; i < a; i++) { b = i * i; log(b); } if(a === 10) { // Function assignments will only result in hoisted variables but the function body will not be hoisted // Only by using a real function declaration the whole function will be hoisted with its body f = function() { log(a); }; f(); } x(); }(window.console.log));
使用嚴格等
總是使用 === 精確的比較操作符,避免在判斷的過程中,由 JavaScript 的強制類型轉換所造成的困擾。例如:
(function(log){ 'use strict'; log('0' == 0); // true log('' == false); // true log('1' == true); // true log(null == undefined); // true var x = { valueOf: function() { return 'X'; } }; log(x == 'X'); }(window.console.log));
等同== 和嚴格等===的區別
- ==, 兩邊值類型不同的時候,要先進行類型轉換,再比較。
- ===,不做類型轉換,類型不同的一定不等。
==等同操作符
- 如果兩個值具有相同類型,會進行===比較,返回===的比較值
- 如果兩個值不具有相同類型,也有可能返回true
- 如果一個值是null另一個值是undefined,返回true
- 如果一個值是string另個是number,會把string轉換成number再進行比較
- 如果一個值是true,會把它轉成1再比較,false會轉成0
console.log( false == null ) // false console.log( false == undefined ) // false console.log( false == 0 ) // true console.log( false == '' ) // true console.log( false == NaN ) // false console.log( null == undefined ) // true console.log( null == 0 ) // false console.log( null == '' ) // false console.log( null == NaN ) // false console.log( undefined == 0) // false console.log( undefined == '') // false console.log( undefined == NaN) // false console.log( 0 == '' ) // true console.log( 0 == NaN ) // false
總結:
- false 除了和自身比較為 true 外,和 0,”” 比較也為 true
- null 只和 undefined 比較時為 true, 反過來 undefined 也僅和 null 比較為 true,沒有第二個
- 0 除了和 false 比較為 true,還有空字符串 ”” 和空數組 []
- 空字符串 ” 除了和 false 比較為 true,還有一個數字 0
==, >, <, +, -, … 這些操作符所造成的隱式類型轉換都是無副作用的,它不會改變變量本身保存的值。,但是,如果你覆寫某個對象的 valueOf/toString的話,==就會產生副作用.
例如:
Array.prototype.valueOf = function() { this[0]++; return this; } var x = [1, 2, 3]; x == 0; console.log(x); // [2, 2, 3]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
===操作符:
- 要是兩個值類型不同,返回false
- 要是兩個值都是number類型,並且數值相同,返回true
- 要是兩個值都是stirng,並且兩個值的String內容相同,返回true
- 要是兩個值都是true或者都是false,返回true
- 要是兩個值都是指向相同的Object,Arraya或者function,返回true
- 要是兩個值都是null或者都是undefined,返回true
真假判斷
js中以下內容為假:
- false
- null
- undefined
- 0
- ’ ‘(空字符串)
- NaN
設置默認參數
邏輯操作符 || 和 && 也可被用來返回布爾值。如果操作對象為非布爾對象,那每個表達式將會被自左向右地做真假判斷。基於此操作,最終總有一個表達式被返回回來。這在變量賦值時,是可以用來簡化你的代碼的。例如:如果x不存在且y不存在,x=1;如果x存在y存在,x = y
不適用eval()函數
如eval的字面意思來說,惡魔,使用eval()函數會帶來安全隱患。
eval()函數的作用是返回任意字符串,當作js代碼來處理。
this關鍵字
只在對象構造器、方法和在設定的閉包中使用 this 關鍵字。this 的語義在此有些誤導。它時而指向全局對象(大多數時),時而指向調用者的定義域(在 eval 中),時而指向 DOM 樹中的某一節點(當用事件處理綁定到 HTML 屬性上時),時而指向一個新創建的對象(在構造器中),還時而指向其它的一些對象(如果函數被 call() 和 apply() 執行和調用時)。
正因為它是如此容易地被搞錯,請限制它的使用場景:
- 在構造函數中
- 在對象的方法中(包括由此創建出的閉包內)
首選函數式風格
函數式編程讓你可以簡化代碼並縮減維護成本,因為它容易復用,又適當地解耦和更少的依賴。
接下來的例子中,在一組數字求和的同一問題上,比較了兩種解決方案。第一個例子是經典的程序處理,而第二個例子則是采用了函數式編程和 ECMA Script 5.1 的數組方法。
不推薦:
(function(log){ 'use strict'; var arr = [10, 3, 7, 9, 100, 20], sum = 0, i; for(i = 0; i < arr.length; i++) { sum += arr[i]; } log('The sum of array ' + arr + ' is: ' + sum) }(window.console.log));
推薦(函數式編程):
(function(log){ 'use strict'; var arr = [10, 3, 7, 9, 100, 20]; var sum = arr.reduce(function(prevValue, currentValue) { return prevValue + currentValue; }, 0); log('The sum of array ' + arr + ' is: ' + sum); }(window.console.log));
修改內建對象原型鏈
修改內建的諸如 Object.prototype 和 Array.prototype 是被嚴厲禁止的。修改其它的內建對象比如 Function.prototype,雖危害沒那么大,但始終還是會導致在開發過程中難以 debug 的問題,應當也要避免。
三元條件判斷(if 的快捷方法)
用三元操作符分配或返回語句。在比較簡單的情況下使用,避免在復雜的情況下使用。沒人願意用 10 行三元操作符把自己的腦子繞暈。
不推薦:
if(x === 10) { return 'valid'; } else { return 'invalid'; }
推薦:
return x === 10 ? 'valid' : 'invalid'
JSHint
在js規范中,有很多規范都是樣式上的規范而不是邏輯上的規范,比如盡量使用===而不是==,我們可以使用JSHint或者JSLint,Javascript代碼驗證工具,這種工具可以檢查你的代碼並提供相關的代碼改進意見。我個人使用的是JSHint,所以就以這個為例.
webstorm內置JSHint
對於ws愛好者來說,我沒有用過其他的編譯器,ws基本上能滿足你的所有需求(最新的ws集成了vue)。
在Settings => language & frameworks => JavaScript => Code Quality Tolls => JSHint 
其余規范參考官方文檔:http://jshint.com/docs/
CSS規范
id和class的命名
ID和class的名稱總是使用可以反應元素目的和用途的名稱,或其他通用的名稱,代替表象和晦澀難懂的名稱。
不推薦:
.fw-800 { font-weight: 800; } .red { color: red; }
推薦:
.heavy { font-weight: 800; } .important { color: red; }
合理的使用ID
一般情況下ID不應該被用於樣式,並且ID的權重很高,所以不使用ID解決樣式的問題,而是使用class
不推薦:
#content .title { font-size: 2em; }
推薦:
.content .title { font-size: 2em; }
css選擇器中避免使用標簽名
從結構、表現、行為分離的原則來看,應該盡量避免css中出現HTML標簽,並且在css選擇器中出現標簽名會存在潛在的問題。
使用子選擇器
很多前端開發人員寫選擇器鏈的時候不使用 直接子選擇器(注:直接子選擇器和后代選擇器的區別)。
有時,這可能會導致疼痛的設計問題並且有時候可能會很耗性能。
然而,在任何情況下,這是一個非常不好的做法。
如果你不寫很通用的,需要匹配到DOM末端的選擇器, 你應該總是考慮直接子選擇器。
不推薦:
.content .title { font-size: 2rem; }
推薦:
.content > .title { font-size: 2rem; }
盡量使用縮寫屬性
盡量使用縮寫屬性對於代碼效率和可讀性是很有用的,比如font屬性。
不推薦:
border-top-style: none; font-family: palatino, georgia, serif; font-size: 100%; line-height: 1.6; padding-bottom: 2em; padding-left: 1em; padding-right: 1em; padding-top: 0;
推薦:
border-top: 0; font: 100%/1.6 palatino, georgia, serif; padding: 0 1em 2em;
0后面不帶單位
省略0后面的單位,
推薦:
padding-bottom: 0; margin: 0;
屬性格式
- 為了保證一致性和可擴展性,每個聲明應該用分號結束,每個聲明換行。
- 屬性名的冒號后使用一個空格。出於一致性的原因,屬性和值(但屬性和冒號之間沒有空格)的之間始終使用一個空格。
- 每個選擇器和屬性聲明總是使用新的一行。
- 屬性選擇器或屬性值用雙引號(””),而不是單引號(”)括起來。
- URl值(url())不要使用引號。
作為實踐,遵循以下順序:
結構型屬性:
- display
- position,left,top,right,etc
- overflow,float,clear,etc
- margin,padding
表現型屬性:
- background,border,etc
- font,text
不推薦:
.box { font-family: 'Arial', sans-serif; border: 3px solid #ddd; left: 30%; position: absolute; text-transform: uppercase; background-color: #eee; right: 30%; isplay: block; font-size: 1.5rem; overflow: hidden; padding: 1em; margin: 1em; }
推薦:
.box { display: block; position: absolute; left: 30%; right: 30%; overflow: hidden; margin: 1em; padding: 1em; background-color: #eee; border: 3px solid #ddd; font-family: 'Arial', sans-serif; font-size: 1.5rem; text-transform: uppercase; }
原文地址:
