1、格式规范
1.1 命名
1.1.1 变量、函数、函数参数、类的方法命名采用 Camel 命名法
1.1.2 类命名采用 Pascal 命名法
1.1.3 枚举变量采用 Pascal命名法,枚举属性采用全部大写字母,单词间下划线分隔
const TargetStatus = {
READING: 1,
READY_TO_GO: 2
}
1.2 括号
1.2.1 箭头函数的参数仅一个,且不包含解构时,参数部分括号省略
//Good
list.map(item=>item*2)
//Bad
list.map((item)=>item*2)
1.2.2 箭头函数的函数体仅一个单行表达式语句,且作为返回值时,省略{}、return
若单行表达式过长,或函数体仅一个 Object Literal
返回值时,可使用 ()
包裹
//Good
list.map(item=>({result:item*2}))
//Bad
list.map(item=>{return {result:item * 2}})
1.2.3 在 if/else/for/do/while
语句中,即使只有一行,也不得省略块 {...}
2、语法规范
2.1 变量
2.1.1 使用 let
、const
定义变量,不使用 var
明确变量作用域范围,当变量未被修改的情况下,优先使用 const
2.1.2 声明并赋值时,每次只能声明一个变量;仅声明不赋值时,允许声明多个变量
// Good
const a = [];
const b = {};
// Bad
const arr = [], obj = {};
2.2 解构
2.2.1 不要使用3层以上的解构
2.2.2 若不节省解构时产生的中间变量,解构表达式右边不允许是ObjectLiteral
`ArrayLiteral`
此时解构将降低代码可读性,也并无收益
// Good
const {first: firstName, last: lastName} = person
// Bad
const {one, two} = {one:1,two:2}
2.3 条件
2.3.1 相等判断使用类型严格的 ===
2.3.2 当判断 null
`undefined时使用
==`
2.3.3 对于相同变量或表达式的多值条件,用 switch
代替 if
也可通过config[key]
的方式,结合空合并运算符 ??
(Nullish coalescing operator)判断
2.4 循环
2.4.1 不要在循环体中包含函数表达式,事先将函数提取到函数体外
2.5 类型
2.5.1 类型判断优先 typeof
、Array.isArray()
、instanceof
2.5.2 转换为 boolean
类型时,使用 Boolean
() 方法
2.6 字符串
2.6.1 字符串开头和结束使用单引号 ''
2.7 对象
2.7.1 检测对象是否有某个属性时,常用方法比较
常见几种判断对象中属性是否存在的方法比较:
- 判断自身属性:hasOwnProperty():判断指定对象的某个自身属性是否存在(含枚举、不可枚举属性)
- 获得自身可枚举属性:Object.keys(obj):得到一个对象自身的可枚举属性数组,再去检测属性是否存在
- 获得自身所有属性:Reflect.ownKeys(target):返回一个包含所有自身属性的数组
判断自身属性和继承属性
- . 或 [ ]:判断指定对象的自有属性和继承属性中是否存在某属性,无法判断值为 undefined的属性
- in 运算符:判断指定对象的自有属性和继承属性中是否存在某属性,可判断值为 undefined的属性
- Object.prototype.hasOwnProperty.call(obj,key):检测对象是否含某个自有或继承属性时使用
- Reflect.has(obj, key):判断一个对象是否存在某个属性,和 in 运算符的功能完全相同
2.7.2 使用
Object.keys
、Object.entries
进行对象遍历Object.keys
、Object.entries
分别得到一个对象自身的可枚举属性数组、可枚举值数组。不推荐使用for ... in
进行对象遍历,可以避免遗漏hasOwnProperty
而产生的错误。for in 用于遍历给定对象原型链上的所有可枚举字段,如果对象实例之前存在继承关系,使用 fon in 迭代对象时的副作用将更明显。2.7.3 避免直接调用
避免Object.prototype
上的方法{hasOwnProperty: false}
或Object.create(null)
的情况//Good
const has = Object.prototype.hasOwnProperty
console.log(has.call(object,key))
//Bad
console.log(object.hasOwnProperty(key))
2.7.4 对象浅拷贝时,使用
相比...
Object.assign
, 代码更简洁,性能更高//Good
const obj = {...oldObj}
//Bad
const obj = Object.assign({},oldObj)
2.8 数组
2.8.1 合并两个或多个数组时,使用
相比 concat , 数组展开对...
Iterable
有更好兼容性2.8.2 数组遍历时,使用原生方法代替
for in
、for of
2.9 ES Module
2.9.1 建议优先使用
有更强大地语法支持,支持ES Module
tree shaking
进行性能优化,通过构建工具很方便地转换为其他模块系统2.9.2 建议优先使用
后者有以下缺点:named export
, 而不是default export
难以重构或确保一致性,因为它们可以在代码库中命名为除实际名称之外的任何名称
- 难以通过自动化工具进行分析或提供代码智能感知和自动完成
- 它们打破了 treeShaking 因为不是导入您想要使用的单个函数,而是强制 webpack 导入整个文件以及它所具有的任何其他死代码,从而导致更大的包大小
2.10 异步
2.10.1 不得将可并行的 IO 过程串行化
并行 IO 消耗时间约等于 IO 时间最大的那个过程,串行的话消耗时间将是所有过程的时间之和//Good
const getTablePage = async ()=>{
const [table,page] = await Promise.all([getTable(),getPage()]);
return {table,page}
}
//Bad
const getTablePage = async ()=>{
const table = await getTable();
const page = await getPage();
return Promise.resolve({table,page})
}
2.10.2 建议使用
Promise
代替callback