前端開發規範
一、HTML
1.語義化标簽
HTML5 提供了很多語義化元素,更好地幫助描述内容。希望你能從這些豐富的标簽庫中受益。
<!-- bad -->
<div id="main">
<div class="article">
<div class="header">
<h1>Blog post</h1>
<p>Published: <span>21st Feb, 2015</span></p>
</div>
<p>…</p>
</div>
</div>
<!-- good -->
<main>
<article>
<header>
<h1>Blog post</h1>
<p>Published: <time datetime="2015-02-21">21st Feb, 2015</time></p>
</header>
<p>…</p>
</article>
</main>

請確定正确使用語義化的标簽,錯誤的用法甚至不如保守的用法。
<!-- bad -->
<h1>
<figure>
<img alt=Company src=logo.png>
</figure>
</h1>
<!-- good -->
<h1>
<img alt=Company src=logo.png>
</h1>
簡潔
確定代碼簡潔,不要再采用XHTML的舊做法。
<!-- bad -->
<!doctype html>
<html lang=en>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf-8" />
<title>Contact</title>
<link rel=stylesheet href=style.css type=text/css />
</head>
<body>
<h1>Contact me</h1>
<label>
Email address:
<input type=email [email protected] required=required />
</label>
<script src=main.js type=text/javascript></script>
</body>
</html>
<!-- good -->
<!doctype html>
<html lang=en>
<meta charset=utf-8>
<title>Contact</title>
<link rel=stylesheet href=style.css>
<h1>Contact me</h1>
<label>
Email address:
<input type=email [email protected] required>
</label>
<script src=main.js></script>
</html>
HTML5 doctype
為每個 HTML 頁面的第一行添加标準模式(standard mode)的聲明,這樣能夠確定在每個浏覽器中擁有一緻的展現。
<!DOCTYPE html>
<html>
<head>
</head>
</html>
語言屬性
根據 HTML5 規範:
強烈建議為 html 根元素指定 lang 屬性,進而為文檔設定正确的語言。這将有助于語音合成工具确定其所應該采用的發音,有助于翻譯工具确定其翻譯時所應遵守的規則等等。
更多關于 lang 屬性的知識可以從
此規範中了解。
這裡列出了
語言代碼表。
<html lang="en">
<!-- ... -->
</html>
IE 相容模式
IE 支援通過特定的 <meta> 标簽來确定繪制目前頁面所應該采用的 IE 版本。除非有強烈的特殊需求,否則最好是設定為 edge mode,進而通知 IE 采用其所支援的最新的模式。
閱讀這篇
stack overflow上的文章可以獲得更多有用的資訊。
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
字元編碼
通過明确聲明字元編碼,能夠確定浏覽器快速并容易的判斷頁面内容的渲染方式。這樣做的好處是,可以避免在 HTML 中使用字元實體标記(character entity),進而全部與文檔編碼一緻(一般采用 UTF-8 編碼)。
<head>
<meta charset="UTF-8">
</head>
可用性
可用性不應該是事後才考慮的事情。你可以通過簡單的修改做出不錯的效果,例如:
- 正确使用alt屬性
- 確定連結和按鈕正确使用(不要用
這種粗暴的做法)<div class=button>
- 不依賴于顔色來傳達資訊
- 給表單做好lable标記
<!-- bad -->
<h1><img alt="Logo" src="logo.png"></h1>
<!-- good -->
<h1><img alt="My Company, Inc." src="logo.png"></h1>
性能
除非有非要在加載内容前加載腳本的必要性由,不然别這樣做,這樣會阻礙網頁渲染。如果你的樣式表很大,必須獨立放到一個檔案裡。兩次HTTP 請求不會顯著降低性能。
<!-- bad -->
<!doctype html>
<meta charset=utf-8>
<script src=analytics.js></script>
<title>Hello, world.</title>
<p>...</p>
<!-- good -->
<!doctype html>
<meta charset=utf-8>
<title>Hello, world.</title>
<p>...</p>
<script src=analytics.js></script>
屬性順序
HTML 屬性應該按照特定的順序出現以保證易讀性。
id class name data-xxx src, for, type, href title, alt aria-xxx, role value style
二、CSS
分号
不能漏寫分号
/* bad */
div {
color: red
}
/* good */
div {
color: red;
}
流
盡量不要改變元素預設行為。保持預設的文本流。比如,移出一個圖檔下面的一個白塊,不影響原本的顯示:
/* bad */
img {
display: block;
}
/* good */
img {
vertical-align: middle;
}
類似的,盡量不要改變浮動方式。
/* bad */
div {
width: 100px;
position: absolute;
right: 0;
}
/* good */
div {
width: 100px;
margin-left: auto;
}
選擇器
緊密耦合DOM選擇器,三個層級以上建議加class:
/* bad */
div:first-of-type :last-child > p ~ *
/* good */
div:first-of-type .info
避免不必要的寫法:
/* bad */
img[src$=svg], ul > li:first-child {
opacity: 0;
}
/* good */
[src$=svg], ul > :first-child {
opacity: 0;
}
指明
不要讓代碼難于重寫,讓選擇器更精确,減少ID、避免使用!important
/* bad */
.bar {
color: green !important;
}
.foo {
color: red;
}
/* good */
.foo.bar {
color: green;
}
.foo {
color: red;
}
覆寫
覆寫樣式會使維護和調試更困難,是以要盡量避免。
/* bad */
li {
visibility: hidden;
}
li:first-child {
visibility: visible;
}
/* good */
li + li {
visibility: hidden;
}
繼承
不要把可繼承的樣式重複聲明:
/* bad */
div h1, div p {
text-shadow: 0 1px 0 #fff;
}
/* good */
div {
text-shadow: 0 1px 0 #fff;
}
簡潔性
保持代碼的簡潔。使用屬性縮寫。不必要的值不用寫。
/* bad */
div {
transition: all 1s;
top: 50%;
margin-top: -10px;
padding-top: 5px;
padding-right: 10px;
padding-bottom: 20px;
padding-left: 10px;
}
/* good */
div {
transition: 1s;
top: calc(50% - 10px);
padding: 5px 10px 20px;
}
語言
能用英文的時候不用數字。
/* bad */
:nth-child(2n + 1) {
transform: rotate(360deg);
}
/* good */
:nth-child(odd) {
transform: rotate(1turn);
}
動畫
除了變形和改變透明度用animation,其他盡量使用transition。
/* bad */
div:hover {
animation: move 1s forwards;
}
@keyframes move {
100% {
margin-left: 100px;
}
}
/* good */
div:hover {
transition: 1s;
transform: translateX(100px);
}
機關
可以不用機關時就不用。建議用rem。時間機關用s比ms好。
/* bad */
div {
margin: 0px;
font-size: .9em;
line-height: 22px;
transition: 500ms;
}
/* good */
div {
margin: 0;
font-size: .9rem;
line-height: 1.5;
transition: .5s;
}
顔色
需要做透明效果是用rgba,否則都用16進制表示:
/* bad */
div {
color: hsl(103, 54%, 43%);
}
/* good */
div {
color: #5a3;
}
繪圖
減少HTTPS請求,盡量用CSS繪圖替代圖檔:
/* bad */
div::before {
content: url(white-circle.svg);
}
/* good */
div::before {
content: "";
display: block;
width: 20px;
height: 20px;
border-radius: 50%;
background: #fff;
}
注釋
/* bad */
div {
// position: relative;
transform: translateZ(0);
}
/* good */
div {
/* position: relative; */
will-change: transform;
}
文法
- 用兩個空格來代替制表符(tab) -- 這是唯一能保證在所有環境下獲得一緻展現的方法。
- 為選擇器分組時,将單獨的選擇器單獨放在一行。
- 為了代碼的易讀性,在每個聲明塊的左花括号前添加一個空格。
- 聲明塊的右花括号應當單獨成行。
- 每條聲明語句的 : 後應該插入一個空格。
- 為了獲得更準确的錯誤報告,每條聲明都應該獨占一行。
- 所有聲明語句都應當以分号結尾。最後一條聲明語句後面的分号是可選的,但是,如果省略這個分号,你的代碼可能更易出錯。
- 對于以逗号分隔的屬性值,每個逗号後面都應該插入一個空格(例如,box-shadow)。
- 不要在 rgb()、rgba()、hsl()、hsla() 或 rect() 值的内部的逗号後面插入空格。這樣利于從多個屬性值(既加逗号也加空格)中區分多個顔色值(隻加逗号,不加空格)。
/* Bad CSS */
.selector, .selector-secondary, .selector[type=text] {
padding:15px;
margin:0px 0px 15px;
background-color:rgba(0, 0, 0, 0.5);
box-shadow:0px 1px 2px #CCC,inset 0 1px 0 #FFFFFF
}
/* Good CSS */
.selector,
.selector-secondary,
.selector[type="text"] {
padding: 15px;
margin-bottom: 15px;
background-color: rgba(0,0,0,.5);
box-shadow: 0 1px 2px #ccc, inset 0 1px 0 #fff;
}
id及class命名
*class應以功能過内容命名,不以表現形式命名,通用且有意義的詞
*class與id單詞字母小寫,多個單詞組成時,使用中劃線“-”分隔
激活及hover的效果class
使用on作為激活狀态的class,使用hover作為移上元素(hover)的class
樣式的聲明順序
1、定位
2、盒模型
3、關于文字
4、關于顔色,背景
5、其他,如:cursor:pointer
.declaration-order {
/*定位 */
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 100;
/* 盒模型 */
display: block;
box-sizing: border-box;
width: 100px;
height: 100px;
padding: 10px;
border: 1px solid #e5e5e5;
border-radius: 3px;
margin: 10px;
float: right;
overflow: hidden;
/* 關于文字 */
font: normal 13px "Helvetica Neue", sans-serif;
line-height: 1.5;
text-align: center;
/* 關于顔色,背景 */
background-color: #f5f5f5;
color: #fff;
opacity: .8;
/*其他 */
cursor: pointer;
}
less文法規範
1.變量,混合的使用
變量,混合,允許我們單獨定義一系列通用的樣式,然後在需要的時候去調用。是以一些公共的樣式規則可以單獨在一個less檔案中定義,其他地方調用,在做全局樣式調整時能很友善的修改
// LESS
@color: #4D926F;
#header {
color: @color;
}
h2 {
color: @color;
}
/* 生成的 CSS */
#header {
color: #4D926F;
}
h2 {
color: #4D926F;
}
//LESS
.bordered {
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
#menu a {
color: #111;
.bordered;
}
.post a {
color: red;
.bordered;
}
/* 生成的 CSS */
#menu a {
color: #111;
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
.post a {
color: red;
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
2.嵌套規則(避免嵌套層級過多)
将嵌套深度限制在2-3級。對于超過3級的嵌套,給予重新評估。這可以避免出現過于詳實的CSS選擇器。 避免大量的嵌套規則。當可讀性受到影響時,将之打斷。推薦避免出現多于20行的嵌套規則出現。
#header {
color: black;
.navigation {
font-size: 12px;
}
.logo {
width: 300px;
&:hover { text-decoration: none }
}
}
3.命名空間
有時候,你可能為了更好組織CSS或者單純是為了更好的封裝,将一些變量或者混合子產品打包起來, 你可以像下面這樣在#bundle中定義一些屬性集之後可以重複使用:
#bundle {
.button () {
display: block;
border: 1px solid black;
background-color: grey;
&:hover { background-color: white }
}
.tab { ... }
.citation { ... }
}
/*你隻需要在 #header a中像這樣引入 .button:*/
#header a {
color: orange;
#bundle > .button;
}
以上HTML和CSS的規範大部分參考github上的 frontend-guidelines 及 編碼規範by@mdo (後面幾個自己新增
三、JavaScript
javascript規範使用的是 Standard 标準,其好處可點選超連結檢視,npm,github等都是使用的此标準。 下文copy的 Standard Style 的具體規則,配合eslint使用
1. 使用兩個空格進行縮進。
eslint: indent
function hello (name) {
console.log('hi', name)
}
2.除需要轉義的情況外,字元串統一使用單引号。
eslint: quotes
console.log('hello there')
$("<div class='box'>")
3.不要定義未使用的變量。
eslint: no-unused-vars
function myFunction () {
var result = something() // avoid
}
4.關鍵字後面加空格。
eslint: keyword-spacing
if (condition) { ... } // ok
if(condition) { ... } // avoid
5.函數聲明時括号與函數名間加空格。
eslint: space-before-function-paren
function name (arg) { ... } // ok
function name(arg) { ... } // avoid
run(function () { ... }) // ok
run(function() { ... }) // avoid
6.始終使用 === 替代 ==。
例外: obj == null 可以用來檢查 null || undefined。
eslint: eqeqeq
if (name === 'John') // ok
if (name == 'John') // avoid
if (name !== 'John') // ok
if (name != 'John') // avoid
7.字元串拼接操作符 (Infix operators) 之間要留白格。
eslint: space-infix-ops
// ok
var x = 2
var message = 'hello, ' + name + '!'
// avoid
var x=2
var message = 'hello, '+name+'!'
8.逗号後面加空格。
eslint: comma-spacing
// ok
var list = [1, 2, 3, 4]
function greet (name, options) { ... }
// avoid
var list = [1,2,3,4]
function greet (name,options) { ... }
9.else 關鍵字要與花括号保持在同一行。
eslint: brace-style
// ok
if (condition) {
// ...
} else {
// ...
}
// avoid
if (condition)
{
// ...
}
else
{
// ...
}
10.多行 if 語句的的括号不能省。
eslint: curly
// ok
if (options.quiet !== true) console.log('done')
// ok
if (options.quiet !== true) {
console.log('done')
}
// avoid
if (options.quiet !== true)
console.log('done')
11.不要丢掉異常進行中err參數。
eslint: handle-callback-err
// ok
run(function (err) {
if (err) throw err
window.alert('done')
})
// avoid
run(function (err) {
window.alert('done')
})
12.使用浏覽器全局變量時加上 window. 字首。
例外: document, console and navigator
eslint: no-undef
window.alert('hi') // ok
13.不允許有連續多行空行。
eslint: no-multiple-empty-lines
// ok
var value = 'hello world'
console.log(value)
// avoid
var value = 'hello world'
console.log(value)
14.對于三元運算符 ? 和 : 與他們所負責的代碼處于同一行。
eslint: operator-linebreak
// ok
var location = env.development ? 'localhost' : 'www.api.com'
// ok
var location = env.development
? 'localhost'
: 'www.api.com'
// avoid
var location = env.development ?
'localhost' :
'www.api.com'
15.每個 var 關鍵字單獨聲明一個變量。
eslint: one-var
// ok
var silent = true
var verbose = true
// avoid
var silent = true, verbose = true
// avoid
var silent = true,
verbose = true
16.條件語句中指派語句使用括号包起來。這樣使得代碼更加清晰可讀,而不會認為是将條件判斷語句的全等号(===)錯寫成了等号(=)。
eslint: no-cond-assign
// ok
while ((m = text.match(expr))) {
// ...
}
// avoid
while (m = text.match(expr)) {
// ...
}
17.單行代碼塊兩邊加空格。
eslint: block-spacing
function foo () {return true} // avoid
function foo () { return true } // ok
18.對于變量和函數名統一使用駝峰命名法。
eslint: camelcase
function my_function () { } // avoid
function myFunction () { } // ok
var my_var = 'hello' // avoid
var myVar = 'hello' // ok
19.不允許有多餘的行末逗号。
eslint: comma-dangle
var obj = {
message: 'hello', // avoid
}
20.始終将逗号置于行末。
eslint: comma-style
var obj = {
foo: 'foo'
,bar: 'bar' // avoid
}
var obj = {
foo: 'foo',
bar: 'bar' // ok
}
21.檔案末尾留一空行。
elint: eol-last
22.函數調用時辨別符與括号間不留間隔。
eslint: func-call-spacing
console.log ('hello') // avoid
console.log('hello') // ok
23.鍵值對當中冒号與值之間要留白白。
eslint: key-spacing
var obj = { 'key' : 'value' } // avoid
var obj = { 'key' :'value' } // avoid
var obj = { 'key':'value' } // avoid
var obj = { 'key': 'value' } // ok
24.構造函數要以大寫字母開頭。
eslint: new-cap
function animal () {}
var dog = new animal() // avoid
function Animal () {}
var dog = new Animal() // ok
25.無參的構造函數調用時要帶上括号。
eslint: new-parens
function Animal () {}
var dog = new Animal // avoid
var dog = new Animal() // ok
26.對象中定義了存值器,一定要對應的定義取值器。
eslint: accessor-pairs
var person = {
set name (value) { // avoid
this.name = value
}
}
var person = {
set name (value) {
this.name = value
},
get name () { // ok
return this.name
}
}
27.子類的構造器中一定要調用 super
eslint: constructor-super
class Dog {
constructor () {
super() // avoid
}
}
class Dog extends Mammal {
constructor () {
super() // ok
}
}
28.使用數組字面量而不是構造器。
eslint: no-array-constructor
var nums = new Array(1, 2, 3) // avoid
var nums = [1, 2, 3] // ok
29.避免使用 arguments.callee 和 arguments.caller。
eslint: no-caller
function foo (n) {
if (n <= 0) return
arguments.callee(n - 1) // avoid
}
function foo (n) {
if (n <= 0) return
foo(n - 1)
}
30.避免對類名重新指派。
eslint: no-class-assign
class Dog {}
Dog = 'Fido' // avoid
31.避免修改使用 const 聲明的變量。
eslint: no-const-assign
const score = 100
score = 125 // avoid
32.避免使用常量作為條件表達式的條件(循環語句除外)。
eslint: no-constant-condition
if (false) { // avoid
// ...
}
if (x === 0) { // ok
// ...
}
while (true) { // ok
// ...
}
33.正則中不要使用控制符。
eslint: no-control-regex
var pattern = /\x1f/ // avoid
var pattern = /\x20/ // ok
34.不要使用 debugger。
eslint: no-debugger
function sum (a, b) {
debugger // avoid
return a + b
}
35.不要對變量使用 delete 操作。
eslint: no-delete-var
var name
delete name // avoid
36.不要定義備援的函數參數。
eslint: no-dupe-args
function sum (a, b, a) { // avoid
// ...
}
function sum (a, b, c) { // ok
// ...
}
37.類中不要定義備援的屬性。
eslint: no-dupe-class-members
class Dog {
bark () {}
bark () {} // avoid
}
38.對象字面量中不要定義重複的屬性。
eslint: no-dupe-keys
var user = {
name: 'Jane Doe',
name: 'John Doe' // avoid
}
39.switch 語句中不要定義重複的 case 分支。
eslint: no-duplicate-case
switch (id) {
case 1:
// ...
case 1: // avoid
}
40.同一子產品有多個導入時一次性寫完。
eslint: no-duplicate-imports
import { myFunc1 } from 'module'
import { myFunc2 } from 'module' // avoid
import { myFunc1, myFunc2 } from 'module' // ok
41.正則中不要使用空字元。
eslint: no-empty-character-class
const myRegex = /^abc[]/ // avoid
const myRegex = /^abc[a-z]/ // ok
42.不要解構空值。
eslint: no-empty-pattern
const { a: {} } = foo // avoid
const { a: { b } } = foo // ok
43.不要使用 eval()。
eslint: no-eval
eval( "var result = user." + propName ) // avoid
var result = user[propName] // ok
44.catch 中不要對錯誤重新指派。
eslint: no-ex-assign
try {
// ...
} catch (e) {
e = 'new value' // avoid
}
try {
// ...
} catch (e) {
const newVal = 'new value' // ok
}
45.不要擴充原生對象。
eslint: no-extend-native
Object.prototype.age = 21 // avoid
46.避免多餘的函數上下文綁定。
eslint: no-extra-bind
const name = function () {
getName()
}.bind(user) // avoid
const name = function () {
this.getName()
}.bind(user) // ok
47.避免不必要的布爾轉換。
eslint: no-extra-boolean-cast
const result = true
if (!!result) { // avoid
// ...
}
const result = true
if (result) { // ok
// ...
}
48.不要使用多餘的括号包裹函數。
eslint: no-extra-parens
const myFunc = (function () { }) // avoid
const myFunc = function () { } // ok
49.switch 一定要使用 break 來将條件分支正常中斷。
eslint: no-fallthrough
switch (filter) {
case 1:
doSomething() // avoid
case 2:
doSomethingElse()
}
switch (filter) {
case 1:
doSomething()
break // ok
case 2:
doSomethingElse()
}
switch (filter) {
case 1:
doSomething()
// fallthrough // ok
case 2:
doSomethingElse()
}
50.不要省去小數點前面的0。
eslint: no-floating-decimal
const discount = .5 // avoid
const discount = 0.5 // ok
51.避免對聲明過的函數重新指派。
eslint: no-func-assign
function myFunc () { }
myFunc = myOtherFunc // avoid
52.不要對全局隻讀對象重新指派。
eslint: no-global-assign
window = {} // avoid
53.注意隐式的 eval()。
eslint: no-implied-eval
setTimeout("alert('Hello world')") // avoid
setTimeout(function () { alert('Hello world') }) // ok
54.嵌套的代碼塊中禁止再定義函數。
eslint: no-inner-declarations
if (authenticated) {
function setAuthUser () {} // avoid
}
55.不要向 RegExp 構造器傳入非法的正規表達式。
eslint: no-invalid-regexp
RegExp('[a-z') // avoid
RegExp('[a-z]') // ok
56.不要使用非法的空白符。
eslint: no-irregular-whitespace
function myFunc () /*<NBSP>*/{} // avoid
57.禁止使用 iterator。
eslint: no-iterator
Foo.prototype.__iterator__ = function () {} // avoid
58.外部變量不要與對象屬性重名。
eslint: no-label-var
var score = 100
function game () {
score: 50 // avoid
}
59.不要使用标簽語句
eslint: no-labels
label:
while (true) {
break label // avoid
}
60.不要書寫不必要的嵌套代碼塊。
eslint: no-lone-blocks
function myFunc () {
{ // avoid
myOtherFunc()
}
}
function myFunc () {
myOtherFunc() // ok
}
61.不要混合使用空格與制表符作為縮進。
eslint: no-mixed-spaces-and-tabs
62.除了縮進,不要使用多個空格。
eslint: no-multi-spaces
const id = 1234 // avoid
const id = 1234 // ok
63.不要使用多行字元串。
eslint: no-multi-str
const message = 'Hello \ world' // avoid
64.new 建立對象執行個體後需要指派給變量。
eslint: no-new
new Character() // avoid
const character = new Character() // ok
65.禁止使用 Function 構造器。
eslint: no-new-func
var sum = new Function('a', 'b', 'return a + b') // avoid
66.禁止使用 Object 構造器。
eslint: no-new-object
let config = new Object() // avoid
67.禁止使用 new require。
eslint: no-new-require
const myModule = new require('my-module') // avoid
68.禁止使用 Symbol 構造器。
eslint: no-new-symbol
const foo = new Symbol('foo') // avoid
69.禁止使用原始包裝器。
eslint: no-new-wrappers
const message = new String('hello') // avoid
70.不要将全局對象的屬性作為函數調用。
eslint: no-obj-calls
const math = Math() // avoid
71.不要使用八進制字面量。
eslint: no-octal
const num = 042 // avoid
const num = '042' // ok
72.字元串字面量中也不要使用八進制轉義字元。
eslint: no-octal-escape
const copyright = 'Copyright \251' // avoid
73.使用 __dirname 和 __filename 時盡量避免使用字元串拼接。
eslint: no-path-concat
const pathToFile = __dirname + '/app.js' // avoid
const pathToFile = path.join(__dirname, 'app.js') // ok
74.使用 getPrototypeOf 來替代 proto。
eslint: no-proto
const foo = obj.__proto__ // avoid
const foo = Object.getPrototypeOf(obj) // ok
75.不要重複聲明變量。
eslint: no-redeclare
let name = 'John'
let name = 'Jane' // avoid
let name = 'John'
name = 'Jane' // ok
76.正則中避免使用多個空格。
eslint: no-regex-spaces
const regexp = /test value/ // avoid
const regexp = /test {3}value/ // ok
const regexp = /test value/ // ok
77.return 語句中的指派必需有括号包裹。
eslint: no-return-assign
function sum (a, b) {
return result = a + b // avoid
}
function sum (a, b) {
return (result = a + b) // ok
}
78.避免将變量指派給自己。
eslint: no-self-assign
name = name // avoid
79.避免将變量與自己進行比較操作。
esint: no-self-compare
if (score === score) {} // avoid
80.避免使用逗号操作符。
eslint: no-sequences
if (doSomething(), !!test) {} // avoid
81.不要随意更改關鍵字的值。
eslint: no-shadow-restricted-names
let undefined = 'value' // avoid
82.禁止使用稀疏數組(Sparse arrays)。
eslint: no-sparse-arrays
let fruits = ['apple',, 'orange'] // avoid
83.不要使用制表符。
eslint: no-tabs
84.正确使用 ES6 中的字元串模闆。
eslint: no-template-curly-in-string
const message = 'Hello ${name}' // avoid
const message = `Hello ${name}` // ok
85.使用 this 前請確定 super() 已調用。
eslint: no-this-before-super
class Dog extends Animal {
constructor () {
this.legs = 4 // avoid
super()
}
}
86.用 throw 抛錯時,抛出 Error 對象而不是字元串。
eslint: no-throw-literal
throw 'error' // avoid
throw new Error('error') // ok
87.行末不留白格。
eslint: no-trailing-spaces
88.不要使用 undefined 來初始化變量。
eslint: no-undef-init
let name = undefined // avoid
let name
name = 'value' // ok
89.循環語句中注意更新循環變量。
eslint: no-unmodified-loop-condition
for (let i = 0; i < items.length; j++) {...} // avoid
for (let i = 0; i < items.length; i++) {...} // ok
90.如果有更好的實作,盡量不要使用三元表達式。
eslint: no-unneeded-ternary
let score = val ? val : 0 // avoid
let score = val || 0 // ok
91.return,throw,continue 和 break 後不要再跟代碼。
eslint: no-unreachable
function doSomething () {
return true
console.log('never called') // avoid
}
92.finally 代碼塊中不要再改變程式執行流程。
eslint: no-unsafe-finally
try {
// ...
} catch (e) {
// ...
} finally {
return 42 // avoid
}
93.關系運算符的左值不要做取反操作。
eslint: no-unsafe-negation
if (!key in obj) {} // avoid
94.避免不必要的 .call() 和 .apply()。
eslint: no-useless-call
sum.call(null, 1, 2, 3) // avoid
95.避免使用不必要的計算值作對象屬性。
eslint: no-useless-computed-key
const user = { ['name']: 'John Doe' } // avoid
const user = { name: 'John Doe' } // ok
96.禁止多餘的構造器。
eslint: no-useless-constructor
class Car {
constructor () { // avoid
}
}
97.禁止不必要的轉義。
eslint: no-useless-escape
let message = 'Hell\o' // avoid
98.import, export 和解構操作中,禁止指派到同名變量。
eslint: no-useless-rename
import { config as config } from './config' // avoid
import { config } from './config' // ok
99.屬性前面不要加空格。
eslint: no-whitespace-before-property
user .name // avoid
user.name // ok
100.禁止使用 with。
eslint: no-with
with (val) {...} // avoid
101.對象屬性換行時注意統一代碼風格。
eslint: object-property-newline
const user = {
name: 'Jane Doe', age: 30,
username: 'jdoe86' // avoid
}
const user = { name: 'Jane Doe', age: 30, username: 'jdoe86' } // ok
const user = {
name: 'Jane Doe',
age: 30,
username: 'jdoe86'
}
102.代碼塊中避免多餘留白。
eslint: padded-blocks
if (user) {
// avoid
const name = getName()
}
if (user) {
const name = getName() // ok
}
103.展開運算符與它的表達式間不要留白白。
eslint: rest-spread-spacing
fn(... args) // avoid
fn(...args) // ok
104.遇到分号時空格要後留前不留。
eslint: semi-spacing
for (let i = 0 ;i < items.length ;i++) {...} // avoid
for (let i = 0; i < items.length; i++) {...} // ok
105.代碼塊首尾留白格。
eslint: space-before-blocks
if (admin){...} // avoid
if (admin) {...} // ok
106.圓括号間不留白格
eslint: space-in-parens
getName( name ) // avoid
getName(name) // ok
107.一進制運算符後面跟一個空格。
eslint: space-unary-ops
typeof!admin // avoid
typeof !admin // ok
108.注釋首尾留白格。
eslint: spaced-comment
//comment // avoid
// comment // ok
/*comment*/ // avoid
/* comment */ // ok
109.模闆字元串中變量前後不加空格。
eslint: template-curly-spacing
const message = `Hello, ${ name }` // avoid
const message = `Hello, ${name}` // ok
110.檢查 NaN 的正确姿勢是使用 isNaN()。
eslint: use-isnan
if (price === NaN) { } // avoid
if (isNaN(price)) { } // ok
111.用合法的字元串跟 typeof 進行比較操作。
eslint: valid-typeof
typeof name === 'undefimed' // avoid
typeof name === 'undefined' // ok
112.自調用匿名函數 (IIFEs) 使用括号包裹。
eslint: wrap-iife
const getName = function () { }() // avoid
const getName = (function () { }()) // ok
const getName = (function () { })() // ok
113.yield * 中的 * 前後都要有空格。
eslint: yield-star-spacing
yield* increment() // avoid
yield * increment() // ok
114.請書寫優雅的條件語句(avoid Yoda conditions)。
eslint: yoda
if (42 === age) { } // avoid
if (age === 42) { } // ok
115.使用分号。
eslint: semi
window.alert('hi') // avoid
window.alert('hi'); // ok
116.不要使用 (, [, or ` 等作為一行的開始。在沒有分号的情況下代碼壓縮後會導緻報錯,而堅持這一規範則可避免出錯。
** eslint: no-unexpected-multiline **
// ok
;(function () {
window.alert('ok')
}())
// avoid
(function () {
window.alert('ok')
}())
// ok
;[1, 2, 3].forEach(bar)
// avoid
[1, 2, 3].forEach(bar)
// ok
;`hello`.indexOf('o')
// avoid
`hello`.indexOf('o')
備注:上面的寫法隻能說聰明過頭了。
相比更加可讀易懂的代碼,那些看似投巧的寫法是不可取的。
譬如:
;[1, 2, 3].forEach(bar)
建議的寫法是:
var nums = [1, 2, 3]
es6文法規範
1.let 取代 var
ES6 提出了兩個新的聲明變量的指令:let和const。其中,let完全可以取代var,因為兩者語義相同,而且let沒有副作用。
2.全局常量const
在全局環境,不應該設定變量,隻應設定常量
好處:
優于
const
有幾個原因。一個是
let
可以提醒閱讀程式的人,這個變量不應該改變;另一個是
const
比較符合函數式程式設計思想,運算不改變值,隻是建立值,而且這樣也有利于将來的分布式運算;最後一個原因是 JavaScript 編譯器會對
const
進行優化,是以多使用
const
,有利于提高程式的運作效率,也就是說
const
和
let
的本質差別,其實是編譯器内部的處理不同。 const聲明常量還有兩個好處,一是閱讀代碼的人立刻會意識到不應該修改這個值,二是防止了無意間修改變量值所導緻的錯誤。
const
3.使用解構指派
使用數組成員對變量指派時,優先使用解構指派。
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];
// good
const [first, second] = arr;
函數的參數如果是對象的成員,優先使用解構指派。
// bad
function getFullName(user) {
const firstName = user.firstName;
const lastName = user.lastName;
}
// good
function getFullName(obj) {
const { firstName, lastName } = obj;
}
// best
function getFullName({ firstName, lastName }) {
}
如果函數傳回多個值,優先使用對象的解構指派,而不是數組的解構指派。這樣便于以後添加傳回值,以及更改傳回值的順序。
// bad
function processInput(input) {
return [left, right, top, bottom];
}
// good
function processInput(input) {
return { left, right, top, bottom };
}
const { left, right } = processInput(input);
4.對象
對象盡量靜态化,一旦定義,就不得随意添加新的屬性。如果添加屬性不可避免,要使用Object.assign方法。
// bad
const a = {};
a.x = 3;
// if reshape unavoidable
const a = {};
Object.assign(a, { x: 3 });
// good
const a = { x: null };
a.x = 3;
如果對象的屬性名是動态的,可以在創造對象的時候,使用屬性表達式定義。
// bad
const obj = {
id: 5,
name: 'San Francisco',
};
obj[getKey('enabled')] = true;
// good
const obj = {
id: 5,
name: 'San Francisco',
[getKey('enabled')]: true,
};
另外,對象的屬性和方法,盡量采用簡潔表達法,這樣易于描述和書寫。
var ref = 'some value';
// bad
const atom = {
ref: ref,
value: 1,
addValue: function (value) {
return atom.value + value;
},
};
// good
const atom = {
ref,
value: 1,
addValue(value) {
return atom.value + value;
},
};
5.數組
使用擴充運算符(...)拷貝數組。
// bad
const len = items.length;
const itemsCopy = [];
let i;
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
// good
const itemsCopy = [...items];
使用 Array.from 方法,将類似數組的對象轉為數組。
const foo = document.querySelectorAll('.foo');
const nodes = Array.from(foo);
6.函數
立即執行函數可以寫成箭頭函數的形式。
(() => {
console.log('Welcome to the Internet.');
})();
那些需要使用函數表達式的場合,盡量用箭頭函數代替。因為這樣更簡潔,而且綁定了 this。
// bad
[1, 2, 3].map(function (x) {
return x * x;
});
// good
[1, 2, 3].map((x) => {
return x * x;
});
// best
[1, 2, 3].map(x => x * x);
簡單的、單行的、不會複用的函數,建議采用箭頭函數。如果函數體較為複雜,行數較多,還是應該采用傳統的函數寫法。
7.Map結構
注意區分 Object 和 Map,隻有模拟現實世界的實體對象時,才使用 Object。如果隻是需要key: value的資料結構,使用 Map 結構。因為 Map 有内建的周遊機制。
let map = new Map(arr);
for (let key of map.keys()) {
console.log(key);
}
for (let value of map.values()) {
console.log(value);
}
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
8.class
總是用 Class,取代需要 prototype 的操作。因為 Class 的寫法更簡潔,更易于了解。
// bad
function Queue(contents = []) {
this._queue = [...contents];
}
Queue.prototype.pop = function() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
// good
class Queue {
constructor(contents = []) {
this._queue = [...contents];
}
pop() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
}
使用extends實作繼承,因為這樣更簡單,不會有破壞instanceof運算的危險。
// bad
const inherits = require('inherits');
function PeekableQueue(contents) {
Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function() {
return this._queue[0];
}
// good
class PeekableQueue extends Queue {
peek() {
return this._queue[0];
}
}
9.使用promise時
一般來說,不要在then方法裡面定義失敗狀态的回調函數(即then的第二個參數),總是使用catch方法
// bad
promise
.then(function(data) {
// success
}, function(err) {
// error
});
// good
promise
.then(function(data) { //cb
// success
})
.catch(function(err) {
// error
});
新增
i++
盡量不要使用i++,盡量使用i+=1;(除了for循環)
四、vue規範
1.vue方法放置順序
1.1 components
1.2 props
1.3 data
1.4 created
1.5 mounted
1.6 activited
1.7 update
1.8 beforeRouteUpdate
1.9 metods
1.10 filter
1.11 computed
1.12 watch
2.method 自定義方法命名
2.1 動賓短語(good:jumpPage、openCarInfoDialog)(bad:go、nextPage、show、open、login)
2.2 ajax 方法以 get、post 開頭,以 data 結尾(good:getListData、postFormData)(bad:takeData、confirmData、getList、postForm)
2.3 事件方法以 on 開頭(onTypeChange、onUsernameInput)
2.4 init、refresh 單詞除外
2.5 盡量使用常用單詞開頭(set、get、open、close、jump)
2.6 駝峰命名(good: getListData)(bad: get_list_data、getlistData)
3.生命周期方法注意點
3.1 不在 mounted、created 之類的方法寫邏輯,取 ajax 資料,
3.2 在 created 裡面監聽 Bus 事件
4.基于子產品開發
原則:每一個vue元件首先必須專注于解決一個單一的問題,獨立的,可複用的,微小的和可測試的。 如果你的元件做了太多的事或是變得臃腫,請将其拆成更小的元件并保持單一的原則。
5.Vue 元件命名
有意義的: 不過于具體,也不過于抽象
簡短: 2 到 3 個單詞
具有可讀性: 以便于溝通交流
<!-- 推薦 -->
<app-header></app-header>
<user-list></user-list>
<range-slider></range-slider>
<!-- 避免 -->
<btn-group></btn-group> <!-- 雖然簡短但是可讀性差. 使用 `button-group` 替代 -->
<ui-slider></ui-slider> <!-- ui 字首太過于寬泛,在這裡意義不明确 -->
<slider></slider> <!-- 與自定義元素規範不相容 -->
6.驗證元件的props
提供預設值。
使用 type 屬性校驗類型。
使用 props 之前先檢查該 prop 是否存在。
<template>
<input type="range" v-model="value" :max="max" :min="min">
</template>
<script type="text/javascript">
export default {
props: {
max: {
type: Number, // 這裡添加了數字類型的校驗
default() { return 10; },
},
min: {
type: Number,
default() { return 0; },
},
value: {
type: Number,
default() { return 4; },
},
},
};
</script>
7.隻在需要時建立元件
Vue.js 是一個基于元件的架構。如果你不知道何時建立元件可能會導緻以下問題:
- 如果元件太大, 可能很難重用和維護;
- 如果元件太小,你的項目就會(因為深層次的嵌套而)被淹沒,也更難使元件間通信;
規則
- 首先,盡可能早地嘗試建構出諸如模态框、提示框、工具條、菜單、頭部等這些明顯的(通用型)元件。總之,你知道的這些元件以後一定會在目前頁面或者是全局範圍内需要。
- 第二,在每一個新的開發項目中,對于一整個頁面或者其中的一部分,在進行開發前先嘗試思考一下。如果你認為它有一部分應該是一個元件,那麼就建立它吧。
- 最後,如果你不确定,那就不要。避免那些“以後可能會有用”的元件污染你的項目。它們可能會永遠的隻是(靜靜地)待在那裡,這一點也不聰明。注意,一旦你意識到應該這麼做,最好是就把它打破,以避免與項目的其他部分構成相容性和複雜性。
注釋規範
1.在vscode中使用vscode-fileheader插件,生成頭部檔案注釋
2.普通的注釋
2.1 總是在單行注釋符後留一個空格
// this is comment
2.2 總是在多行注釋的結束符前留一個空格(使星号對齊)
/* */
2.3 不要把注釋寫在多行注釋的開始符、結束符所在行
// bad
/* start end */
// good
/* here is line 1 here is line 2 */
2.4 不要編寫無意義的注釋
// 初始化value變量為0
var value = 0;
2.5 如果某段代碼有功能未實作,或者有待完善,必須添加“TODO”标記,“TODO”前後應留一個空格
// TODO 未處理IE6-8的相容性
function setOpacity(node, val) {
node.style.opacity = val;
}
3.文檔注釋
文檔注釋将會以預定格式出現在API文檔中。它以“/”開頭,以“/”結束,其間的每一行均以“”開頭(均與開始符的第一個“”對齊),且注釋内容與“”間留一個空格。
3.1 @module。聲明子產品
/** * 子產品說明 * @module 子產品名 */
/** * Core子產品提供最基礎、最核心的接口 * @module Core */
3.2 @class。聲明類
/** * 類說明 * @class 類名 * @constructor */
@class必須搭配@constructor或@static使用,分别标記非靜态類與靜态類。
/** * 節點集合類 * @class NodeList * @constructor * @param {ArrayLike<Element>} nodes 初始化節點 */
3.3 @method。聲明函數或類方法
/** * 方法說明 * @method 方法名 * @for 所屬類名 * @param {參數類型} 參數名 參數說明 * @return {傳回值類型} 傳回值說明 */
沒有指定@for時,表示此函數為全局或子產品頂層函數。當函數為靜态函數時,必須添加@static;當函數有參數時,必須使用@param;當函數有傳回值時,必須使用@return。
/** * 傳回目前集合中指定位置的元素 * @method * @for NodeList * @param {Number} [i=0] 位置下标。如果為負數,則從集合的最後一個元素開始倒數 * @return {Element} 指定元素 */
- @param。聲明函數參數,必須與@method搭配使用。
- 當參數出現以下情況時,使用對應的格式:[參數名]
- 參數有預設值 [參數名 = 預設值]
3.4 @property。聲明類屬性
/** * 屬性說明 * @property {屬性類型} 屬性名 */
原文釋出時間為:2018年01月20日
原文作者:
放開那個女孩本文來源:
開源中國如需轉載請聯系原作者