【青训营】写好JS——写代码最应该关注什么?

228 阅读2分钟

这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战

嗟予贫贱年将老,学古忧时满怀抱。

前言

如何写好JS,什么才叫好的代码?这是个很难回答的问题,一千个人中有一千个哈姆雷特,本文只是浅显地讨论一下写代码最应该关注什么?

先来看一段代码:

//判断一个mat2d矩阵是否是单位矩阵
function isUnitMatrix2d(m) {
    return m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1 && m[4] === 0 && m[5] === 0;
}

单从代码优雅性来说,这个代码看着就挺low的,但它是4.8k⭐的开源项目spritejs里的真实代码,这段代码是负责图形渲染的,也就是说每一帧的计算都要用到这段代码,在这样的场景下,我们最应该关注的是效率性能,而不是代码风格。

所以,一般来说,写代码要结合使用场景,关注以下几个方面:

image-20220128174423825

当年的Left-pad事件

很多流行的npm模块因为引入了一个叫做left-pad的模块,导致无法正常运行,这个模块中只有11行代码,就是一个简单的字符串处理函数:

module.exports = leftpad;
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;
}

这个事情本身的槽点很多,首先就是NPM模块粒度的问题,为什么一个函数11行代码就构成了一个模块,粒度是不是太细了?然后是代码风格问题,这个代码的可读性很高,但是代码效率很低,时间复杂度为O(N),总体而言,代码本身没什么大问题。

但是考虑到效率,还是可以对代码进行改进的,最影响效率的地方就是循环部分,我们并不需要一个一个的拼接,可以采用repeat()方法简化同时提升效率:

function leftpad(str, len, ch=""){
  str = "" + str;
  const padLen = len - str.length;

  if (padLen <= 0){
    return str;
  } else {
    return ("" + ch).repeat(padLen) + str;
  }
}

以前的MDN文档中关于repeat()的核心代码是:

var rpt = "";
for(;;) {
  if ((count & 1) == 1) {
    rpt += str;
  }
  count >>>= 1;
  
  if (count == 0){
    break;
  }
  str += str;
}

就是通过位运算减少循环次数,比如传进来的数是20,它的二进制是0001 0100,每次比较最后一位,如果为1就拼接上,然后右移一位,重复这个过程即可,时间复杂度为O(log2N)。

但是现在MDN的repeat()中核心代码是:

var maxCount = str.length * count;
count = Math.floor(Math.log(count) / Math.log(2));
// while循环
while (count) {
  str += str;
  count--;
}
str += str.substring(0, maxCount - str.length);
return str;

这跟最开始没有改进时一样,所以说大部分场景不需要注重效率,代码风格才是我们最应该注意的。