变量

  • 名称应该是可描述、有意义的
  • 小驼峰或是大驼峰书写。
  • 名称不要有冗余的上下文
  • 声明经常复用的常量,全局常量可以用全大写字母、下划线分割单词风格书写。

    函数

  • 名称要有意义

  • 不要害怕太长
  • 通常是动词
  • 使用默认参数而不是在函数体内额外的条件语句
  • 限制参数数量
    • 如果参数过多:
      • 函数要做的事情太多,需要拆分
      • 参数应该作为专用数据结构传递(对象
  • 一个函数别做太多事情
  • 如果只用一个布尔值就能分为没重复的两部分,那干脆就拆成两个函数
  • 有大量重复代码,能复用的情况坚决复用。(有点废话,但是有时确实需要自己提醒一下自己)
  • 保持纯函数,避免副作用——直接返回新值,而不是操作传入的数据

    • 数组的展开运算符有很好的效果

      条件语句

  • 不要双重否定——!isNotxxx

  • 尽可能简写——!!将其他任何值转换为布尔值

    1. if (firstName !== "" && firstName !== null && firstName !== undefined) {
    2. // ...
    3. }
    4. //better ✅
    5. if (!!firstName) {
    6. // ...
    7. }
  • 减少分支,尽早return,使代码线性化、更具可读性且不那么复杂

  • 使用map>借用对象>switch>if、else。(下文详细讲)

  • 使用可选链接?. ??

    • 关于??
      1. const email = user?.email ?? "N/A";

      并发

  • 使用Promise减少回调防止代码嵌套过深

  • 或者Async 和 Await ```javascript do1(function (err, xxx) { do2(a1, function (err, xxx) { do3(a2, function (err, xxx) {
    1. do4(a3, function (err, xxx) {
    2. doErr(a4, function (err) {
    3. throw new Error(err);
    4. });
    5. });
    }); }); });

// 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); } }

  1. <a name="BpQdW"></a>
  2. ## 错误处理
  3. 处理抛出的错误和reject的promise
  4. ```javascript
  5. try {
  6. // Possible erronous code
  7. } catch (e) {
  8. console.log(e);
  9. }
  10. // better ✅
  11. try {
  12. // Possible erronous code
  13. } catch (e) {
  14. // Follow the most applicable (or all):
  15. // 1- More suitable than console.log
  16. console.error(e);
  17. // 2- Notify user if applicable
  18. alertUserOfError(e);
  19. // 3- Report to server
  20. reportErrorToServer(e);
  21. // 4- Use a custom error handler
  22. throw new CustomError(e);
  23. }

注释

  • 只注释业务逻辑,太简单的不要注释
    • 所以也需要代码写的可读
  • 使用git版本控制从而在git log查看历史,而不是依靠注释

    一些优雅的书写方法

    或许不用if else

    三元运算符

  • 允许的情况下,如简单的表达式,三元运算符替代if-else

    ?? 运算符

  • ??运算符的使用 ```javascript const sthLog = sth ?? “none” console.log(sth)

//等效于 if(sth){ console.log(sth) }else{ console.log(“none”) }

  1. <a name="AFsHl"></a>
  2. ### 短路评估
  3. ```javascript
  4. if(flag){
  5. doSth()
  6. }
  7. //短路
  8. 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*/}],
    1. [/^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)) }

  1. **小技巧:**拼接为字符串后利用正则表达式
  2. <a name="o89j6"></a>
  3. ## 从数组中删除重复项
  4. 借助Set,将原数组转为Set 后再转换为数组
  5. - new Set()将原数组转为Set——此时删除了重复项
  6. - 展开运算符再将其转换为数组
  7. ```javascript
  8. const uniqueArr = [...new Set(Arr)]

可选链?.

有时你不能确定待放问的属性究竟存不存在,如果访问了不存在的属性,那必然会崩溃报错。如果还用if-else或者&&连一串判断,又属实拉垮了。

  1. console.log(human?.wing)//不存在的话就会打印 undefined

交换变量

借助解构赋值

  1. [a,b] = [b,a]

将其他值转换为布尔值

!! 上文也提到了,具体没什么好说的。

扩展运算符

[...xxx]xxx(一个可迭代的对象)转换为数组。

  • 可以用来合并数组
  • 在数组中添加东西
    • 与push的区别就是 它返回的是一个新的数组,而不是在原来的数组上操作——有没有想到纯函数呢

      解构赋值

      1. const human = {
      2. age:18,
      3. name:'zzz',
      4. height:180,
      5. weight:130,
      6. }
      7. 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]; } }

// better tallMan = humans.find((human) => human.height === >= 170);

  1. <a name="J0EgW"></a>
  2. ## for与forEach
  3. ```javascript
  4. for(let i = 0;i < arrs.length; i++){
  5. doSth(arrs.[i])
  6. }
  7. //better
  8. arrs.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”); }

  1. <a name="GghLS"></a>
  2. ## 或许不用Math
  3. - `~~` 也可以对一个数字四舍五入
  4. - `**` 也可以对一个数字幂运算
  5. - `|` 将float 转 int
  6. ```javascript
  7. // chars[Math.floor(Math.random() * chars.length)]
  8. chars[(Math.random() * chars.length) | 0]

类中自动绑定

使用箭头函数就可以不再次专门进行**bind**

截取数组

  • 直接改短数组的length可以简洁地删去数组后面的部分
  • slice 是较快的