ECMAScript 是 Mutl-paradigm 語言,因此存在多種不同風格寫法,統一程式碼風格有助於團隊合作。
Tab
Space 2
ASI
// bad
import Vue from 'vue';
let x = x + 1;
// good
import Vue from 'vue'
let x = x + 1
ECMAScript 支援 ASI (Automatic Semicolon Insertion),會在尾部自動新增 ;
,因此可省略。
Naming Convetion
Variable
// bad
let total_count = 10
let first-name = 'John'
let IsDone = true
// good
let totalCount = 10
let firstName = 'John'
let isDone = true
Primitive variable 使用 noun + camelCase 命名。
// bad
const totalCount = 10
const firstName = 'John'
const isDone = true
// good
const TOTAL_COUNT = 10
const FIRST_NAME = 'John'
const IS_DONE = true
Constant 使用 noun + all uppercase 命名,複合字以 _
隔開。
const
只對 primitive 有效,對 object 與 array 無效
Object
// bad
let printedBook = {
book_title: 'FP in JavaScript',
BookPrice: 100
}
// good
let printedBook = {
bookTitle: 'FP in JavaScript',
bookPrice: 100
}
Object 與 property 使用 noun
+ camelCamel 命名。
Array
// bad
let printedBook = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
// good
let printedBooks = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
Array 使用 複數 noun
+ camelCase 命名。
Function
// bad
let fetch_books = () => {}
let fetch-books = () => {}
let FetchBooks = () => {}
// good
let fetchBooks = () => {}
Function name 使用 camelCase 命名。
// bad
let bookFetched = () => {}
// good
let multiply = (x, y) => x * y
let fetchBooks = () => {}
Function 使用 verb 或 verb + noun 命名方式:
- 若回傳為單數,則 noun 為單數
- 若回傳為 array,則 noun 為複數
單 verb 適合 helper function
verb + noun 適合一般 function
// bad
let fetchBooks = (page-num, PageSize) => {}
// good
let fetchBooks = (pageNum, pageSize) => {}
Parameter 使用 noun + camelCase 命名。
// bad
let insertLabel = () => {}
// good
let addLabel = () => {}
新增資料時使用 add
為 prefix 較簡短。
// bad
let getHistoryLabel = () => {}
// good
let fetchHistoryLabel = () => {}
get
適合 getter,fetch
適合 Knex 或 Axios 抓資料。
// bad
let updateLabel = () => {}
// good
let editLabel = () => {}
修改資料時使用 edit
為 prefix 較簡短。
// bad
let deleteLabel = () => {}
// good
let delLabel = () => {}
刪除資料時使用 del
為 prefix 較簡短。
// bad
let whereNo = no => () => {}
let makeWhereNo = no => () => {}
// good
let genWhereNo = no => () => {}
gen
適合 higher order function,專門 return function。
Class
// bad
let myBook = function(title) {
this.title = title
}
class myBook {
constructor(title, price) {
this.title
}
}
// good
let MyBook = function(title) {
this.title = title
}
class MyBook {
constructor(title, price) {
this.title
}
}
Constructor function 或 class 的名稱使用 noun + CamelCase。
ECMAScript 只有在 constructor function 或 class 使用 CamelCase,其他都用 camelCase
Variable
// bad
var x = 1
// good
let x = 1
var
會有 hoisting 與 function scope 問題,一律使用 let
無 hoisting 且為 {}
block scope。
String
Single Quote
// bad
let str = "123"
let str = `123`
// good
let str = '123'
String 使用 single quote。
String Concatenation
// bad
let key = 'pkg/status/' + pId + '/' + dId
// good
let key = `pkg/status/${pId}/${dId}`
使用 template string 取代 string concatenation。
Template String
// bad
let name = 'Sam'
let greeting = `Hello ${ name }`
// good
let name = 'Sam'
let greeting = `Hello ${name}`
{
與 variable 之間沒有 space。
{
用於 object 時有 space,用於 string 時沒有 space
Multiple Line
// bad
let errorMessage = 'This is a super long error that was thrown because \
of Batman. When you stop to think about how Batman had anything to do \
with this, you would get nowhere \
fast.'
// bad
let errorMessage = 'This is a super long error that was thrown because ' +
'of Batman. When you stop to think about how Batman had anything to do ' +
'with this, you would get nowhere fast.';
// good
const errorMessage = `This is a super long error
that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.`
多行 string 請用 ES6 的 template string。
Statement
if
// bad
if(isDone) {
}
// good
if (isDone) {
}
if
與 (
之間有 space。
// bad
if ( isDone ) {
}
// good
if (isDone) {
}
(
與 expression 之間不要有 space。
switch
// bad
switch(expr)
case 'Orange':
...
break
case 'Apple'
...
break
default:
}
// good
switch (expr)
case 'Orange':
...
break
case 'Apple'
...
break
default:
}
switch
與 (
之間有 space。
for
// bad
for(let x of arr)
{
}
// good
for (let x of arr) {
}
()
與 {
在同一行。
Math Operator
// bad
let x=y+5
// good
let x = y + 5
Operator 與 operand 之間有 space。
Expression
Mutiple Line Ternary Operator
// bad
let isDone = isPass
? true
: false
// good
let isDone = passed ?
true :
false
?
與 :
寫在後面。
Object
Object Literal
// bad
let obj = { name : 'Sam' }
// good
let obj = { name: 'Sam' }
:
左側不加 space,右側加 space。
Property
let obj = { name: 'Sam '}
// bad
obj['name']
// good
obj.name
若 property 名稱不是 variable,使用 .
存取。
let obj = { name: 'Sam' }
let propName = 'name'
obj[propName]
當 property 名稱為 variable 時才使用 []
。
One Line
// bad
let obj = {name: 'Sam'}
// good
let obj = { name: 'Sam' }
{
與 property 之間有 space。
Multiple Line
// bad
let obj =
{
title: 'FP in JavaScript',
price: 100
}
// good
let obj = {
title: 'FP in JavaScript',
price: 100
}
{
與 =
在同一行。
Method
// bad
let obj = {
title: 'FP in JavaScript',
getTitle: function() {
return this.title
}
}
// good
let obj = {
title: 'FP in JavaScript',
getTitle() {
return this.title
}
}
Object 中的 method 使用 ES6 的 property shorthand。
Object Destructuring
// bad
let f = ({title, price}) => `${title}: ${price}`
// good
let f = ({ title, price }) => `${title}: ${price}`
{
與 property 之間有 space。
// bad
let f = ({ title, ,price }) => `${title}: ${price}`
// good
let f = ({ title, _, price }) => `${title}: ${price}`
不需要解構的 variable 以 _
、__
… 表示。
Array
Index
let data = [1, 2, 3]
// bad
let x = data[ 0 ]
// good
let x = data[0]
[
與 index 之間不要有 space。
Multi Line
// bad
let data = [{
title: 'FP in JavaScript', price: 100
}, {
title: 'RxJS in Action', price: 200
}, {
title: 'Speaking JavaScript', price: 300
}]
// good
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
]
多行時 [
與 {
不要在同一行。
// bad
let arr = [ 1, 2, 3 ]
// good
let arr = [1, 2, 3]
[
與 element 之間沒有 space。
Array Destructuring
// bad
let [ from, to ] = getToday()
// good
let [from, to] = getToday()
[
與 element 之間沒有 space。
Enum
// bad
fetchNotification(0)
// good
let typeEnum = {
error: 0,
maintained: 1
}
let fetchNotification(typeEnum.error)
使用 object 模擬 enum,並以 Enum
為 postfix,避免使用 magic number。
Map
// bad
let f = id => {
if (id === 0) return '異常'
else if (id === 1) return '維護'
else return undefined
}
// good
let typeMap = {
0: '異常',
1: '維護'
}
typeMap[id]
建立 object 為對照表,並以 Map
為 postfix。
Function
General
// bad
// function declaration
function f1(x, y) {
return x + y
}
// ok
// function expression
let f2 = function(x, y) {
return x + y
}
// good
// arrow function
let f3 = (x, y) => x + y
優先使用 arrow function,其次 function expression,不要使用 function declaration。
// bad (error)
let MyBook = title => {
this.title = title
}
// good
let MyBook = function(title) {
this.title = title
}
let myBook = new MyBook('FP in JavaScript')
有兩的地方不能使用 arrow function:
- Vue 要 binding
this
時使用 function expression - Constructor function 使用 function expression
凡
this
會變動的就不能使用 arrow function
Function Expression
// bad
lef f = function () {
return 1
}
// good
let f = function() {
return 1
}
function()
與 ()
之間不要有空格。
Argument
// bad
let f = ( x, y, z ) => {}
// good
let f = (x, y, z) => {}
(
與 argument 間不要 space。
Default Argument
// bad
let f = opts => {
opts = opts || {}
}
// good
let f = (opts = {}) => {}
Default argument 使用 ES6 的 =
。
Multline Signature
// bad
let f = (x,
y,
z) => {}
// good
let f = (
x,
y,
z
) => {}
若 signature 過長要換行,需全部換行。
Multiline Invocation
// bad
console.log(x,
y,
z
)
// good
console.log(
x,
y,
z
)
Callback
// bad
[1, 2, 3].map(function(item) {
return item + 1
})
// good
[1, 2, 3].map(x => x + 1)
- Callback 使用 arrow function
- 且 argument 使用
x
,y
,z
// bad
let f = arr => arr.reduce((a, x) => (x.category !== 'FP') ?[...a, {...x, price: x.price * 0.8 }] : [...a, x], [])
// good
let f = arr => arr.reduce((a, x) =>
(x.category !== 'FP') ?
[...a, {...x, price: x.price * 0.8 }] :
[...a, x]
, [])
只有一行的 arrow function 若過長要加以換行。
Arrow Function
// bad
let f = () => 1
// good
let f = _ => 1
沒 argument 時以 _
取代 ()
。
// bad
let f = (x) => x + 1
// good
let f = x => x + 1
單一 argument 時不加 ()
。
// bad
let f = x => {
return x + 1
}
// good
let f = x => x + 1
當 body 只有一行且為回傳值時,不要加 {}
與 return
。
Method Chaining
// bad
[1, 2, 3].filter(x => x % 2 === 1).map(x => x + 1).reduce((a, x) => a += x)
// good
[1, 2, 3]
.filter(x => x % 2 === 1)
.map(x => x + 1)
.reduce((a, x) => a += x)
讓所有 method 的 .
縮排貼齊。
IIFE
// bad
function() { return 1 }()
// good
(function() { return 1 })()
(() => 1)()
IIFE 一律在 anonymous function 加上 ()
。
Class
// bad
let dt = new Date()
// good
let dt = new Date
當 constructor 不傳 argument 時,()
可省略。
Module
Import / Export Braces
// bad
import {map} from 'ramda'
export {x,y}
// good
import { map } from 'ramda'
export { x, y }
import
與 export
時,{
、}
與 variable 間有 space。
// bad
import {
longNameA,
longNameB,
longNameC,
longNameD,
longNameE,
} from 'path'
// good
import { longNameA, longNameB, longNameC } from 'path'
import { longNameD, longNameE } from 'path'