引用
对所有变量使用
const代替var, 如果一定要改变引用值,使用let代替var
// bad
var a = 1;
// good
const b = 1;
// bad
var flag = 0;
if (cond) {
flag = 0
}
// good
let flag = 1;
if (cond) {
flag = 0;
}
对象
创建字面量
// bad
const item = new Object();
// good
const item = {}
创建带计算的属性名
const getKey = (v) => `key${v}`;
// bad
const obj = {
id: 1,
};
obj[getKey(1)] = "wuw";
// good
const obj = {
id: 2,
[getKey(2)] = "polm",
};
速记语法
// bad
const name = "wuw";
const obj = {
name: name,
};
// good
const obj = {
name
}
// bad
const obj1 = {
name: "wuw",
getName: (v) => obj1.name,
};
// good
const obj1 = {
name: "wuw",
getName() {
return obj1.name;
},
};
引号使用,会改变语法高亮
// bad
const obj = {
"id": 1,
"name": "wuw",
"data-test": "haha"
}
// good
const obj = {
id: 1,
name: "wuw",
"data-test": "haha"
}
使用...优先于Object.assign
// very bad
const obj = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 });
delete copy.a;
// good
const obj = { a: 1, b: 2 };
const copy = { ...obj, c: 3 };
const { a, ...noA } = copy;
数组
数组创建
// bad
const arr = new Array();
// good
const arr = [];
数组复制
// bad
const copy = [];
for (let i = 0; const len = item.length; i < len; i++) {
copy[i] = item[i];
}
// good
const copy = [...item];
数组添加元素
const a = [];
// bad
a[a.length] = 1;
// good
a.push(1);
类数组转换
const set = new Set();
// good
const arr = Array.from(set);
// best
const arr = [...set];
解构
对象解构
// bad
function getFullName(user) {
const firstName = user.firstName;
const lastName = user.lastName;
return `${firstName} ${lastName}`;
}
// good
function getFullName(user) {
const { firstName, lastName } = user;
return `${firstName} ${lastName}`;
}
// best
function getFullName({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
数组解构
const arr = [1, 2, 3];
// bad
const a = arr[0];
const b = arr[1];
// good
const [a, b] = arr;
出入参
- 入参超过
3个时,使用对象代替元素, 可以不用考虑顺序
// bad
function func(a1, a2, a3, a4) {
}
// good
function func({ a1, ...res}) {
}
- 出参超过
3个,使用对象代替数组, 可以不用考虑顺序
function func() {
return [a1, a2, a3, a4];
}
// good
function func() {
return { a1, a2, a3, a4 };
}
字符串
// bad - 模板字符串应该包含变量
const str = `aaa`;
// good
const str = "aaa"
// bad
const name = "wuw";
const str1 = ["hi", name, '~'].join();
// bad
const name = "wuw";
const str1 = "hi" + name + "~";
// bad
const name = "wuw";
const str1 = `hi ${ name } ~`;
// good
const name = "wuw";
const str1 = `hi ${name} ~`;
函数
使用命名函数代替函数声明
- 函数声明会被变量提升
- 可读性和可维护性造成影响
// bad
function func1() {
}
// good
const func1 = () => {
}
不在非函数代码块中进行函数声明
// bad
if (cond) {
function fun() {
}
}
// good
let func;
if (cond) {
func = () => {
}
}
函数参数不要使用arguments, 会覆盖原有作用域的arguments, 使用...代替
// very bad
function (a1, arguments) {
}
// good
function (a1, ...args) {
}
函数默认值
// bad - 会改变对象false值
function func(opts) {
opts = opts || {};
}
func(0) // {}
func(NaN) // {}
func(null) // {}
func(undefine) // {}
// good
function func(opts = {}) {
}
func(0) // 0
func(NaN) // NaN
func(null) // null
func(undefine) // {}
将有默认值的参数放在最后
箭头函数
// bad
[1, 2].map((v) => v + 1);
// good
[1, 2].map(v => v + 1);
[1, 2].map(v => (
`llllllllllllllllllllllllllllllllllll${v}onggggggggggggggggggg`
))
[1, 2].map(v => {
const u = v + 1;
return u * v;
})
构造函数
避免空的构造函数
// bad
constructor(...args) {
super(...args);
}
// good
constructor(...args) {
super(...args);
this.name = "wuw";
}
模块
// bad
const module1 = require('./Module');
model.exports = module1.test;
// good
import module1 from './Module';
expoer default module1.test;
// best
import { test } from './Module';
export default test;
相同路径导入
// bad
import foo from 'foo';
import { bar } from 'foo';
// good
import foo, { bar } from 'foo';
导出 - 尽量使用一个导出利于维护
// bad
export function fun() {}
// ok
const func = () => {}
export {
func
}
// good
export default function foo() {}
import位于所有非导入语句上面
import会被提升, 防止出错
// bad
import foo from 'foo';
const COUNT = 10;
import bar form 'bar';
// good
import foo from 'foo';
import bar form 'bar';
const COUNT = 10;
迭代器
使用高阶函数代替迭代器,避免
for-in和for-of循环的使用
- 纯函数,容易维护
map()every()filter()find()findIndex()reducer()some()Object.key()Object.values()Object.entries()对象生成迭代数组
// bad
let sum = 0;
for (let num of numbers) {
sum += num;
}
for (let i = 0, const len = numbers.length; i < len; i++) {
arr.push(numbers[i] + 1);
}
// good
numbers.forEach((num) => {
sum += num;
});
numbers.forEach((num) => {
arr.push(num + 1);
});
// best
const sum = numbers.reduce((total, num) => total + num, 0);
const arr = numbers.map(num => num + 1);
代码风格
操作符
/* -- 判断 - start -- */
// bad
flag == true; // === 代替 ===
const ans = (a > 1 || b > 2 || check()) ? doSomeThing() : doOther()
// good
const a == 1;
const ans = (a > 1 || b > 2 || check())
? doSomeThing()
: doOther();
flag === true;
/* -- 判断 - end -- */
/* -- 长判断 - start -- */
// bad - 长判断
if ((a >= 2 && b < 3) || checkSomething() || (number + getValue() === 6)) {}
// good
if (
(a >= 2 && b < 3)
&& checkSomething()
&& (number + getValue() === 6)
) {}
/* -- 长判断 - end -- */
/* -- 混合操作符使用括号 - start -- */
// bad
const foo = a && b < 0 || c > 0 || d + 1 === 0; //
const ans = a * 3 - b / 2;
// good
const foo = (a && b < 0) || c > 0 || (d + 1 === 0);
const ans = (a * 3) - (b / 2);
/* -- 混合操作符使用括号 - end -- */
空格
使用两个空格作为缩进
// bad - 运算符左右两边加空格
const a=1;
const a= 1;
const b = a+1;
const obj = {a:1}; // 大括号左右两边空格 :右侧空格
if ( cond ) {} // 小括号左右两边不加空格
const ans = a?1:0;
function func(){};
function func () {};
const func=() => {};
const a = 1;? // 行末尾不加空格
if() {}
if (){}
class Dog{
getName(){
}
}
switch (cond) {
}
import {a} from 'sss';
// good
const a = 1;
const b = a + 1;
const obj = { a: 1 };
if (cond) {}
const a = a ? 1 : 0;
function func() {};
const func = () => {};
if () {}
class Dog {
getName() { // 左侧无空格
}
}
switch(cond) {
}
import { a } from 'sss';
空行
- 不同逻辑代码段之间需要空行
- 文件结尾加空行
- 不要用空白行填充代码段
const isEated = checkEated();
if (isEated) {
}
doAnother();
doLasteThing();
// bad
function func() {
console.log('kkk')
}
// good
function func() {
console.log('kkk')
}
变量
// bad
const a = 1, // 容易出现, ;错乱
b = 2,
c = 3;
const a = 1;
let flag = true;
const b = 2;
// good
const a = 1;
const b = 2;
const c = 3;
const a = 1;
const b = 2;
let flag = true;
代码块
// bad
if (cond)
return;
if (cond) { return false; }
if (cond) { //不一换行
}
else {
}
function func() {
if (cond) {
return x;
} else {
return y; // 不需要else
}
}
switch(cond) {
case 1:
// 不加break需要额外写注释
case 2:
doSomething();
break;
// default不能缺少
}
// good
if (cond) return; // 除直接return 都需要加{} 并换行
if (cond) {
return false;
}
if (cond) {
} else {
}
function func() {
if (cond) {
return x;
}
return y;
}
switch(cond) {
case 1:
check();
break;
case 2:
doSomething();
break;
defalut:
// 为空需要写注释
}
链式调用
// bad
const ans = getValue().fist().second().third() 两个以上换行以.开头
// good
const ans = getValue()
.fist()
.second()
.third()
简写代码
// bad
const a = check() ? doSomething() : null;
let flag = 1;
if (cond) {
flag = 0;
}
// good
const a = check() && doSomething();
const flag = cond ? 1 : 0;