前言:团队基于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)