前言:團隊基於ES6和Eslint規則規定代碼規範,本文的目的是梳理和總結團隊如今實行的規範。javascript
做者:鄭靈華,點餐秒付終端團隊成員java
a.規定箭頭函數強制大括號
b.規定箭頭函數參數是否要使用括號
c.規定箭頭函數的箭頭先後的空格規範
d.generator 函數中 號周圍的空格
e.規定rest參數和擴展運算符與他們的參數之間的空格
f.禁止模板字面量中的花括號出現括號
g.強制在 yield 表達式中 * 後面使用空格git
a.規定箭頭函數強制大括號es6
//Eslint文件配置項
'arrow-body-style': ['error', 'as-needed', {
requireReturnForObjectLiteral: false,
}]複製代碼
參數 | 參數說明 | 備註 |
---|---|---|
as-needed | 當大括號是可省略的,強制不使用 | |
requireReturnForObjectLiteral | 不須要顯式返回對象字面量 | 必須與as-needed 搭配使用 |
//項目中正確使用事例
//能夠省略大括號
let foo = () => 0;
//不用顯式返回對象字面量
let foo = () => ({ bar: 0 });
//錯誤對比:
let foo = () => {
return ({bar: 0 });
};複製代碼
b.規定箭頭函數參數是否要使用括號github
//Eslint文件配置項
'arrow-parens': ['error', 'as-needed', {
requireForBlockBody: true,
}]複製代碼
參數 | 參數說明 | 備註 |
---|---|---|
as-needed | 當只有一個參數時容許省略圓括號 | |
requireForBlockBody | 當函數體在一個指令塊中,參數必須用圓括號包含 | 做爲as-needed補充。以函數體是否被 { } 包括快速判斷 |
//項目實踐正確例子
// 只有一個參數容許省略
a.map(x => {
return x * x;
});
// requireForBlockBody 參數做爲補充,上述代碼修改爲
a.map((x) => {
return x * x;
});複製代碼
c.箭頭函數的箭頭先後的空格規範數組
'arrow-spacing': ['error', {
before: true,
after: true
}]複製代碼
參數 | 參數說明 | 備註 |
---|---|---|
before | 箭頭前面有空格 | |
after | 箭頭後面有空格 |
//項目應用
a => a;複製代碼
d.generator 函數中 * 號周圍的空格數據結構
'generator-star-spacing': ['error', {
before: false,
after: true
}]複製代碼
參數 | 參數說明 | 備註 |
---|---|---|
before | *前面沒有空格 | |
after | *後面有空格 |
//項目正確使用示例
function* generator() {}複製代碼
e.不容許rest參數和擴展運算符與他們的參數之間有空格app
'rest-spread-spacing': ['error', 'never']複製代碼
參數 | 參數說明 | 備註 |
---|---|---|
never | 符號和參數之間不能有空格 |
//rest參數
let [a, b, ...arr] = [1, 2, 3, 4, 5]
//擴展運算符
function fn(){}
fn(...args)複製代碼
f.禁止模板字面量中的花括號出現括號less
'template-curly-spacing': 'error'複製代碼
//花括號裏面沒有括號
`hello, ${people.name}!`複製代碼
g.強制在 yield 表達式中 後面使用空格curl
'yield-star-spacing': ['error', 'after']複製代碼
function* generator() {
yield* other();
}複製代碼
a.不能修改類聲明的變量
b.禁止修改const聲明的變量
c.不容許類成員裏有重複的名稱
d.不要重複引入一個模塊
e.禁止在import,export,解構賦值中重命名和原有名字相同
a.不能修改類聲明的變量
'no-class-assign': 'error'複製代碼
// 簡而言之,若是以class Name{}形object-shorthand式出現,那麼Name不能作任何更改和賦值
// 下面例子是正確的。由於A至始至終只是變量
let A = class {
b() {
A = 0;
console.log(A);
}
}
console.log(A); //class
let Foo = new A();
Foo.b(); //0
console.log(A); //0複製代碼
b.禁止修改const聲明的變量
'no-const-assign': 'error'複製代碼
c.不容許類成員裏有重複的名稱
'no-dupe-class-members': 'error'複製代碼
d.不要重複引入一個模塊
'no-duplicate-imports': 'off'複製代碼
//同一個模塊引入兩個變量應該寫在一個大括號裏面
import { merge, find } from 'module';複製代碼
e.禁止在import,export,解構賦值中重命名和原有名字相同
'no-useless-rename': ['error', {
ignoreDestructuring: false,
ignoreImport: false,
ignoreExport: false,
}]複製代碼
//形如{ foo as foo }和{ bar: bar }並無起到重命名的做用,因此應該禁止這種冗餘書寫
import { foo as bar } from "baz";
export { foo as bar } from "foo";
let { [foo]: foo } = bar;複製代碼
a.Symbol類型不能用new關鍵字
b.Symbol定義的時候增長描述語言,便於debug
c.generator函數裏面必定要有yield
d.使用 let 或 const 而不是 var
e.禁止在字面量聲明無用的計算屬性
f.若變量不會再次賦值,使用const聲明
a.Symbol類型不能用new關鍵字
'no-new-symbol': 'error'複製代碼
//symbol應該以函數形式調用
var foo = Symbol('foo');複製代碼
b.Symbol定義的時候增長描述語言,便於debug
'symbol-description': 'error'複製代碼
let foo = Symbol("some description")複製代碼
c.generator函數裏面必定要有yield
'require-yield': 'error'複製代碼
d.使用 let 或 const 而不是 var
'no-var': 'error'複製代碼
e.禁止在字面量聲明無用的計算屬性
'no-useless-computed-key': 'error'複製代碼
//無用的["a"]計算屬性
var foo = {['0+1,234']: "b"};
//改寫成
var foo = { '0+1,234': 0 };複製代碼
f.若變量不會再次賦值,使用const聲明
'prefer-const': ['error', {
destructuring: 'any',
ignoreReadBeforeAssign: true,
}]複製代碼
參數 | 參數說明 | 備註 |
---|---|---|
destructuring | 解構賦值時,全部變量的類型都應該保持一致 | |
ignoreReadBeforeAssign | 忽略聲明和第一次賦值之間的變量 | 也就是不能先定義後賦值 |
//解構賦值時,值要麼都是const要麼都是let
// a0是肯定的,b沒有被賦值
const {a: a0, b} = obj;
const a = a0 + 1;
// a,b都是變量,因此解構賦值定義用let
let {a, b} = obj;
a = a + 1;
b = b + 1;
//錯誤例子,在ignoreReadBeforeAssign=true時,timer的聲明和賦值之間的initialize()函數聲明會被省略。
//從而會在setInterval處報錯函數undefined
let timer;
function initialize() {
if (foo()) {
clearInterval(timer);
}
}
timer = setInterval(initialize, 100);
//正確例子,只要聲明就要賦值!
const timer = setInterval(initialize, 100);
function initialize() {
if (foo()) {
clearInterval(timer);
}
}複製代碼
a. 避免箭頭函數和比較式混淆
b. 使用模板字面量而不是字符串拼接
c. 使用擴展運算符(...)而非.apply()調用可變參數
d. 用rest參數(...變量名)替換arguments
e. 不容許使用parseInt()轉化2,8,16進制
f. 要求使用箭頭函數進行回調
g. 對象字面量語法簡寫
a.避免箭頭函數和比較式混淆
'no-confusing-arrow': ['error', {
allowParens: true,
}]複製代碼
參數 | 參數說明 | 備註 |
---|---|---|
allowParens | 放寬標準,容許箭頭函數使用括號 | 不強制必須用return返回 |
//若是是嚴格模式,會發現即便用圓括號包含,也要用return區分箭頭函數和三元運算比較
var x = a => { return 1 ? 2 : 3; };
var x = (a) => { return 1 ? 2 : 3; };
//若是allowParens=true,則放寬標準
var x = a => (1 ? 2 : 3);
var x = (a) => (1 ? 2 : 3);複製代碼
b.使用模板字面量而不是字符串拼接
'prefer-template': 'error'複製代碼
let str = `Hello, ${name}!`複製代碼
c.使用擴展運算符(...)而非.apply()調用可變參數
'prefer-spread': 'error'複製代碼
//求出一個數組最大元素
Math.max.apply(null, [14, 3, 77])
//等效於
Math.max(...[14, 3, 77])
//等同
Math.max(14, 3, 77)複製代碼
d.用rest參數(...變量名)替換arguments
'prefer-rest-params': 'error'複製代碼
//rest運算符能夠提供一個真正的數組,能顯式表示參數
//而arguments是一個對象,操做中要經過call等手段調用數組方法
function foo(...args) {
console.log(args);
}複製代碼
e. 不容許使用parseInt()轉化2,8,16進制
'prefer-numeric-literals': 'error'複製代碼
//只針對2,8,16進制使用
//數字轉化成其餘進制或者是變量轉化仍是用parseInt
0b111110111 === 503;
0o767 === 503;
0x1F7 === 503;
parseInt(1, 3);
parseInt(foo, 2);複製代碼
f. 要求使用箭頭函數進行回調
'prefer-arrow-callback': ['error', {
allowNamedFunctions: false,
allowUnboundThis: true,
}]複製代碼
參數 | 參數說明 | 備註 |
---|---|---|
allowNamedFunctions | 若是回調函數裏面是命名函數則報錯 | |
allowUnboundThis | 不使用bind()指定this,規則會動態標記this的使用 |
//直接使用this,而不是bind(this)
//回調函數裏是匿名函數
foo(function() { return this.a; });複製代碼
g.對象字面量語法簡寫
'object-shorthand': ['error', 'always', {
ignoreConstructors: false,
avoidQuotes: true,
}]複製代碼
參數 | 參數說明 | 備註 |
---|---|---|
always | 能簡寫就簡寫 | |
ignoreConstructors | 構造函數不能省略 | 必須指定第一個參數 |
avoidQuotes | 對象鍵是字符串時,用長格式 | 必須指定第一個參數 |
// 由於foo對象兩個鍵都是string,因此後面不能省略
var foo = {
"bar-baz": function() {},
"qux": qux
}複製代碼
a. 構造函數必須調用 super
b. 禁止沒必要要的構造函數
c. 派生類函數構造器禁止在super()以前使用this
a. 構造函數必須調用 super
'constructor-super': 'error'複製代碼
//派生類中構造函數必須調用,非派生類的構造函數不能調用super()
class A {
constructor() { }
}
class A extends B {
constructor() {
super();
}
}複製代碼
b. 禁止沒必要要的構造函數
'no-useless-constructor': 'error'複製代碼
//簡單講即是構造器裏面必定要有執行的邏輯代碼
class A {
constructor () {
doSomething();
}
}
//若是沒有特別的邏輯,則類返回空便可
class A { }複製代碼
c. 派生類函數構造器禁止在super()以前使用this
'no-this-before-super': 'error複製代碼
//不然會返回引用錯誤(reference error)
class A extends B {
constructor() {
super();
this.a = 0; // OK, this is after `super()`.
}
}複製代碼
//用class更爲簡潔
class Foo {
constructor(){}
getVal(){}
}
//等價於
Foo.prototype = {
getVal(){}
}複製代碼
class Foo {}
typeof Foo; // Function
Foo === Foo.prototype.constructor; //true複製代碼
const obj = {
id: 5,
name: 'San Francisco',
[getKey('enabled')]: true,
}複製代碼
// 數組解構=>調用時回調數據的順序是一一對應的
function processInput(input) {
// then a miracle occurs
return [left, right, top, bottom];
}
const [left, __, top] = processInput(input);
// 對象解構=>不考慮順序,只要保證變量必須與屬性同名
function processInput(input) {
// then a miracle occurs
return { left, right, top, bottom };
}
const { left, right } = processInput(input);複製代碼
let { foo: baz } = { foo: "aaa", bar: "bbb" };
baz; // "aaa"
foo; // error: foo is not defined複製代碼
//bad code,若是是Boolean,傳進去甚至會改變opts的類型
function handleThings(opts) {
opts = opts || {};
}
//Airbnb 推薦寫法,初始化參數
function handleThings(opts = {}) {}複製代碼
Airbnb JavaScript規範
阮一峯-ES6入門教程
小問ES6理解-進階版
ES6 In Depth (深刻淺出ES6)