如何写好JavaScript(下) | 青训营笔记

166 阅读1分钟

这是我参与「第四届青训营 」笔记创作活动的的第5天

如何写好JavaScript(下)

一、写代码最应该关注什么?

  • 风格?
  • 效率?
  • 约定?
  • 使用场景?
  • 设计?

⭐ 最终写一段好的代码应该从使用场景入手,这样我们才能真正客观地、科学地去评价这段代码的优劣程度。

二、当年的Leftpad事件

❓ Leftpad事件:Leftpad 工具模块被作者从 NPM 上撤下,所有直接或者间接依赖这个模块的 NPM 包全部挂掉了。

原版

  function leftpad(str, len, ch) {
      str = String(str);
      var i = -1;
      if (!ch && ch !== 0) ch = ' ';
      len = len - str.length;
      while (++i < len) {
          str = ch + str;
      }
      return str;
  } 

优化版

  function leftpad(str, len, ch) {
      str = "" + str;
      const padLen = len - str.length;
      if(padLen <= 0) {
        return str;
      }
      return (""+ch).repeat(padLen)+str;
  } 

⭐ 原版的时间复杂度为O(N)O(N),优化版是通过repeat()函数实现的,而repeat()函数采用快速幂的算法,时间复杂度为O(logN)O(logN),因此:

  • 代码更简洁
  • 效率提升
  • 性能更好

三、交通灯状态切换

版本一

code.juejin.cn/pen/7108196… 👉 显而易见,我们不希望看到这样的代码,这样的代码是很难维护的。

版本二(数据抽象)

code.juejin.cn/pen/7108196… 👉 将数据抽象为一个stateList,通过applyState函数递归实现。

版本三(过程抽象)

code.juejin.cn/pen/7108196…

版本四

code.juejin.cn/pen/7108196…

四、判断是否是4的幂

版本一

function isPowerOfFour(num) {
  num = parseInt(num);

  while(num > 1) {
    if(num % 4) return false;
    num /= 4;
  }
  return num === 1;
}

👉 当num > 1时,判断num能否被4整除,不能则返回false;最后判断 num是否为1。

版本二

function isPowerOfFour(num) {
  num = parseInt(num);

  while(num > 1) {
    if(num & 0b11) return false;
    num >>>=2;
  }
  return num === 1;
}

👉 对版本一进行优化,使用位运算来判断能否被4整除。

版本三

function isPowerOfFour(num){
  num = parseInt(num);
  
  return num > 0 &&
         (num & (num - 1)) === 0 &&
         (num & 0xAAAAAAAAAAAAA) === 0;
}

👉 时间复杂度为O(log1)O(log1),通过4的幂的二进制数特性直接判断。

版本四

function isPowerOfFour(num) {
  num = parseInt(num).toString(2);
  
  return /^1(?:00)*$/.test(num);
}

👉 将num转换为string,利用正则表达式来判断。

五、洗牌

错误写法

code.juejin.cn/pen/7108202… 👉 通过测试,我们发现数字越小的数字越有可能在前面,因此这个写法并不是等可能的。

正确写法

code.juejin.cn/pen/7108203… 👉 每次随机取数,再将数放到数组的最后一位。这样就可以实现等可能。

生成器

code.juejin.cn/pen/7108203… 👉 对正确写法进行修改,可以实现一次选择一张牌。

六、分红包

切西瓜法

code.juejin.cn/pen/7108203… 👉 先对红包金额随机分,每次对较大的部分再分,直至分完;但每个红包金额差异较小;时间复杂度为O(NM)O(NM),空间复杂度为O(1)O(1)

抽牌法

code.juejin.cn/pen/7108204… 👉 利用前面所讲的生成器来实现,这样做每个红包金额差异较大,时间复杂度降为O(N)O(N),但空间复杂度为O(N)O(N)