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 箭头函数的参数仅一个,且不包含解构时,参数部分括号省略
//Goodlist.map(item=>item*2)//Badlist.map((item)=>item*2)
1.2.2 箭头函数的函数体仅一个单行表达式语句,且作为返回值时,省略{}、return
若单行表达式过长,或函数体仅一个 Object Literal 返回值时,可使用 () 包裹
//Goodlist.map(item=>({result:item*2}))//Badlist.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 声明并赋值时,每次只能声明一个变量;仅声明不赋值时,允许声明多个变量
// Goodconst a = [];const b = {};// Badconst arr = [], obj = {};
2.2 解构
2.2.1 不要使用3层以上的解构
2.2.2 若不节省解构时产生的中间变量,解构表达式右边不允许是ObjectLiteral`ArrayLiteral`
此时解构将降低代码可读性,也并无收益
// Goodconst {first: firstName, last: lastName} = person// Badconst {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)的情况//Goodconst has = Object.prototype.hasOwnPropertyconsole.log(has.call(object,key))//Badconsole.log(object.hasOwnProperty(key))
2.7.4 对象浅拷贝时,使用
相比...Object.assign, 代码更简洁,性能更高//Goodconst obj = {...oldObj}//Badconst obj = Object.assign({},oldObj)
2.8 数组
2.8.1 合并两个或多个数组时,使用
相比 concat , 数组展开对...Iterable有更好兼容性2.8.2 数组遍历时,使用原生方法代替
for in、for of2.9 ES Module
2.9.1 建议优先使用
有更强大地语法支持,支持ES Moduletree shaking进行性能优化,通过构建工具很方便地转换为其他模块系统2.9.2 建议优先使用
后者有以下缺点:named export, 而不是default export
难以重构或确保一致性,因为它们可以在代码库中命名为除实际名称之外的任何名称
- 难以通过自动化工具进行分析或提供代码智能感知和自动完成
- 它们打破了 treeShaking 因为不是导入您想要使用的单个函数,而是强制 webpack 导入整个文件以及它所具有的任何其他死代码,从而导致更大的包大小
2.10 异步
2.10.1 不得将可并行的 IO 过程串行化
并行 IO 消耗时间约等于 IO 时间最大的那个过程,串行的话消耗时间将是所有过程的时间之和//Goodconst getTablePage = async ()=>{const [table,page] = await Promise.all([getTable(),getPage()]);return {table,page}}//Badconst getTablePage = async ()=>{const table = await getTable();const page = await getPage();return Promise.resolve({table,page})}
2.10.2 建议使用
Promise代替callback
