【青训营】月影老师告诉我写好JavaScript的四大技巧——风格优先
2021/9/27 12:40:56
本文主要是介绍【青训营】月影老师告诉我写好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循环这样的代码了
这篇关于【青训营】月影老师告诉我写好JavaScript的四大技巧——风格优先的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-12百万架构师第十五课:源码分析:Spring 源码分析:SpringMVC核心原理及源码分析|JavaGuide
- 2025-01-11有哪些好用的家政团队管理工具?
- 2025-01-11营销人必看的GTM五个指标
- 2025-01-11办公软件在直播电商前期筹划中的应用与推荐
- 2025-01-11提升组织效率:上级管理者如何优化跨部门任务分配
- 2025-01-11酒店精细化运营背后的协同工具支持
- 2025-01-11跨境电商选品全攻略:工具使用、市场数据与选品策略
- 2025-01-11数据驱动酒店管理:在线工具的核心价值解析
- 2025-01-11cursor试用出现:Too many free trial accounts used on this machine 的解决方法
- 2025-01-11百万架构师第十四课:源码分析:Spring 源码分析:深入分析IOC那些鲜为人知的细节|JavaGuide