变量
- 名称应该是可描述、有意义的
- 小驼峰或是大驼峰书写。
- 名称不要有冗余的上下文
声明经常复用的常量,全局常量可以用全大写字母、下划线分割单词风格书写。
函数
名称要有意义
- 不要害怕太长
- 通常是动词
- 使用默认参数而不是在函数体内额外的条件语句
- 限制参数数量
- 如果参数过多:
- 函数要做的事情太多,需要拆分
- 参数应该作为专用数据结构传递(对象
- 如果参数过多:
- 一个函数别做太多事情
- 如果只用一个布尔值就能分为没重复的两部分,那干脆就拆成两个函数
- 有大量重复代码,能复用的情况坚决复用。(有点废话,但是有时确实需要自己提醒一下自己)
保持纯函数,避免副作用——直接返回新值,而不是操作传入的数据
不要双重否定——
!isNotxxx尽可能简写——
!!将其他任何值转换为布尔值if (firstName !== "" && firstName !== null && firstName !== undefined) {// ...}//better ✅if (!!firstName) {// ...}
减少分支,尽早return,使代码线性化、更具可读性且不那么复杂
使用map>借用对象>switch>if、else。(下文详细讲)
使用可选链接
?.??- 关于??
const email = user?.email ?? "N/A";
并发
- 关于??
使用Promise减少回调防止代码嵌套过深
- 或者Async 和 Await
```javascript
do1(function (err, xxx) {
do2(a1, function (err, xxx) {
do3(a2, function (err, xxx) {
}); }); });do4(a3, function (err, xxx) {doErr(a4, function (err) {throw new Error(err);});});
// better ✅ do1() .then(do2) .then(do3) .then(do4) .catch((err) => throw new Error(err);
// or using Async/Await ✅
async function doSth() { try { const b1 = await do1(); const b2 = await do2(b1); const b3 = await do3(b2); const b4 = await do4(b3); return do5(b4); } catch (e) { throw new Error(err); } }
<a name="BpQdW"></a>## 错误处理处理抛出的错误和reject的promise```javascripttry {// Possible erronous code} catch (e) {console.log(e);}// better ✅try {// Possible erronous code} catch (e) {// Follow the most applicable (or all):// 1- More suitable than console.logconsole.error(e);// 2- Notify user if applicablealertUserOfError(e);// 3- Report to serverreportErrorToServer(e);// 4- Use a custom error handlerthrow new CustomError(e);}
注释
- 只注释业务逻辑,太简单的不要注释
- 所以也需要代码写的可读
使用git版本控制从而在
git log查看历史,而不是依靠注释一些优雅的书写方法
或许不用if else
三元运算符
-
?? 运算符
??运算符的使用 ```javascript const sthLog = sth ?? “none” console.log(sth)
//等效于 if(sth){ console.log(sth) }else{ console.log(“none”) }
<a name="AFsHl"></a>### 短路评估```javascriptif(flag){doSth()}//短路flag && doSth()
如果非常多if else
switch
很明显,第一个想到的应该就是用switch。这应该没什么好说的。
借用对象?
将判断条件作为对象的属性名,将处理逻辑作为对象的属性值,在触发的时候,通过对象属性查找的方式来进行逻辑判断,这种写法适合一元条件判断的情况。
Map
Map与Obecj的区别在于键的设置可以是任意值
这里分享一个我看到的写的非常好的代码片段——
- 判断条件复杂
- 多元判断
- 有重复的处理逻辑
- 凡是guest情况都要发送一个日志埋点,不同status情况也需要单独的逻辑处理
```javascript
const actions = ()=>{
const functionA = ()=>{/do sth/}
const functionB = ()=>{/do sth/}
const functionC = ()=>{/send log/}
return new Map([
//前面的是身份标识,后面数字是活动状态
[/^guest[1-4]$/,functionA],
[/^guest_5$/,functionB],
[/^guest.$/,functionC],
[/^master_1$/, ()=>{/do sth*/}],
]) }[/^master_2$/', ()=>{/*do sth*/}],
const onButtonClick = (identity,status)=>{
let action = […actions()].filter(([key,value])=>(key.test(${identity}_${status})))
action.forEach(([key,value])=>value.call(this))
}
**小技巧:**拼接为字符串后利用正则表达式<a name="o89j6"></a>## 从数组中删除重复项借助Set,将原数组转为Set 后再转换为数组- new Set()将原数组转为Set——此时删除了重复项- 展开运算符再将其转换为数组```javascriptconst uniqueArr = [...new Set(Arr)]
可选链?.
有时你不能确定待放问的属性究竟存不存在,如果访问了不存在的属性,那必然会崩溃报错。如果还用if-else或者&&连一串判断,又属实拉垮了。
console.log(human?.wing)//不存在的话就会打印 undefined
交换变量
借助解构赋值
[a,b] = [b,a]
将其他值转换为布尔值
扩展运算符
[...xxx]将xxx(一个可迭代的对象)转换为数组。
- 可以用来合并数组
- 在数组中添加东西
- 与push的区别就是 它返回的是一个新的数组,而不是在原来的数组上操作——有没有想到纯函数呢
解构赋值
const human = {age:18,name:'zzz',height:180,weight:130,}const {age,name,...stature} = human
模板字符串
使用xxx${variable}xxx而不是'xxx'+variable+'xxx'数组中查询特殊数据
find(callback)```javascript for (let i = 0; i < humans.length; ++i) { if (humans[i].height >= 170) { tallMan = humans[i]; } }
- 与push的区别就是 它返回的是一个新的数组,而不是在原来的数组上操作——有没有想到纯函数呢
// better tallMan = humans.find((human) => human.height === >= 170);
<a name="J0EgW"></a>## for与forEach```javascriptfor(let i = 0;i < arrs.length; i++){doSth(arrs.[i])}//betterarrs.forEach((arr) => doSth(arr))
对象的keys和values
Object.keys()将对象的所有键收集到一个新数组中Object.values()将对象的所有值收集到一个新数组中includes() 和 indexOf()
也许这两个方法都能很好的判断某个值究竟在不在数组之中,但是或许使用includes()的语义更为明显。压缩判断条件
很长的||总是令人讨厌的,也许能取代掉它。 ```javascript if(num == 1 || num == 2 || num == 3){ console.log(“Yay”); }
// better if([1,2,3].includes(num)){ console.log(“Yay”); }
<a name="GghLS"></a>## 或许不用Math- `~~` 也可以对一个数字四舍五入- `**` 也可以对一个数字幂运算- `|` 将float 转 int```javascript// chars[Math.floor(Math.random() * chars.length)]chars[(Math.random() * chars.length) | 0]
类中自动绑定
截取数组
- 直接改短数组的
length可以简洁地删去数组后面的部分 - slice 是较快的
