青训营月影老师告诉我写好JavaScript的四大技巧——风格优先
Posted YK菌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了青训营月影老师告诉我写好JavaScript的四大技巧——风格优先相关的知识,希望对你有一定的参考价值。
如何写好javascript肯定是每一个前端工程师一直以来要思考的问题,月影老师告诉我们一些写好JavaScript的原则,同时也教了一些我们如何写好JavaScript的技巧,今天来继续跟着月影老师学JavaScript吧~~
我们在写代码的时候,最应该关注的什么?
程序是写给人读的,只是偶尔让计算机执行一下。 —— Donald Ervin Knuth(高德纳)
编码风格与编码效率哪个才是写好代码最应该关注的呢?在大多数情况下,对效率没有那么极致的要求时,我们要优先编码风格,编码可读性,这样可以提高我们代码的可维护性。风格与效率,要根据使用场景来判断!
Left-pad事件
回顾一下2016年引起热议的Left-pad事件
图片来自大圣2016年的博客
事件本身有很多槽点
- 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;
}
月影老师说这里这个代码他觉得问题不大,这是一段好懂的代码。
首先谈到NPM模块粒度的问题,为什么一个函数就构成了一个模块,粒度是不是太细了,其实当年的模块化还没有那么完善,tree shaking功能不太行,所以粒度不得不弄这么小。现在来说是粒度太细了,但是在当年来说是无可厚非的。
代码风格问题,这个代码写的可读性很高,很简单的代码。好的代码本身即注释
最后是代码效率,这里确实效率不高,是O(N)的时间复杂度,但是结合实际,我们实际用的时候也不会用到前面拼很多很多的字符的情况,所以这样也是可以的。
综上所述,这段代码没啥问题~
我们来看看为何那么多人吐槽它的效率低,怎么改进能提升这段代码的效率呢?
我们就看循环部分,让你重复一个字符串n次,真的需要n次循环来一步一步的拼串吗?
while(++i < len){
str = ch + str;
}
比如要将 *
重复 100 遍
100
的 二进制是 1100100
while循环相当于是用十进制的思想,连续拼加了100次的*
(感觉这里应该说是数数的思想)
而使用二进制的思想,每次*
都翻倍(2的幂),只需要循环7次就可以完成,我们看下面的代码来理解
这是优化的代码
function leftpad(str, len, ch=""){
str = "" + str;
const padLen = len - str.length;
if(padLen <= 0){
return str;
}else{
return ("" + ch).repeat(padLen) + str;
}
}
这里用到了ES6的一些特性,默认赋值,字符串的repeat
方法,重点是它怎么实现重复n次操作的
它在MDN上给出的ployfill实现中关键代码是这样的定义的
var rpt = ""
for(;;){
if((count & 1) == 1) {
rpt += str;
}
count >>>= 1;
if(count == 0){
break;
}
str += str;
}
关于快速幂的算法解析,可以看我的博文 【算法】浅析使用JavaScript进行快速幂操作
我们来解读一下这段代码。这里用到了位运算: &
与运算 与 >>>
无符号右移运算
count & 1
取count二进制的最低位,判断和1是否相同,相同返回1,否则返回0
count >>> 1
把count的二进制右移一位,即去掉其二进制位的最低位
所以这段代码的意思就是逆序遍历 count 的二进制形式,str每次都翻倍,遇到二进制位是1的就将str拼到rpt中去
还是上面说的重复100次 *
的例子
倒着遍历100的二进制1100100
,每次都对str进行翻倍操作,二进制中遇到1
的时候就让rpt加上当前的str
这里会循环7+1次, str 分别是 1*
(0)、 2*
(0)、4*
(1)、8*
(0)、16*
(0)、32*
(1)、64*
(1),所以最后rpt就是 4+32+64=100个 *
所以这里的时间复杂度是 O(logN) 循环的次数 是 count的二进制的位数
其实还是可以继续优化的
var rpt = "";
do {
rpt += str;
str += str;
count &= count - 1;
} while(count);
count &= count - 1;
可以去掉二进制中最后面的1
1100100
-> 1100000
-> 1000000
-> 0000000
这里循环的次数 是 count的二进制数中1的位数
比如100的二进制是 1100100
,就会循环 3 次
但是这种情况达不到我们要的结果,应该是老师PPT弄错了~或者是我理解错了,如果知道什么情况的,可以留言或者私信教教我
然而有意思的是,现在 MDN 给出的ployfill代码已经更改成使用while循环这样的代码了😂😂😂
while (count) {
str += str;
count--;
}
搞了半天效率又回去了~~ 哈哈
也就是说在大部分场景下,对效率的要求没有那么恐怖,所以注重代码风格优先仍然是写好JavaScript代码的一个重要技巧!
判断单位矩阵
我们看下面这段代码
这段代码对我看来,是有很多问题的
- 太长了,可读性一般
- 拓展性不高
- 封装性不好
但是,这是一段真实的代码
因为这是当前条件下,效率最高的方式,而这个场景是需要效率优先的。
所以说在实际开发中,我们还是要视具体情况而定的。
总结
这里我们学到了使用位运算实行快速幂,来减少循环次数,来提高我们的代码效率
但是实际上,在效率需求不是那么恐怖的情况下,我们更应该关注我们代码的可读性
最后,风格与效率是需要根据实际场合进行取舍的
以上是关于青训营月影老师告诉我写好JavaScript的四大技巧——风格优先的主要内容,如果未能解决你的问题,请参考以下文章
青训营月影老师告诉我写好JavaScript的四大技巧——风格优先
青训营月影老师告诉我写好JavaScript的四大技巧——风格优先
青训营月影老师告诉我写好JavaScript的四大技巧——妙用特性
青训营月影老师告诉我写好JavaScript的三大原则之——过程抽象