[ JavaScript代码质量优化 | 青训营笔记]

101 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天

一、课程主要内容

1、Leftpad事件

2、代码实践1:交通灯

3、代码实:2:洗牌

4、代码实践3:抽红包

二、内容重点

1、Leftpad事件

重点:代码不够简洁、性能有待提升

解决方案:使用repeat方法替代while循环(时间复杂度为O(n)),由于repeat方法使用2进制幂的方法得到待补齐的长度,进一步减小时间复杂度,为O(log2n);

2、代码实践1:交通灯状态切换

版本1:对于后续交通灯状态转换使用setTimeout回调嵌套,代码可读性差,且难以维护;

版本2(数据抽象):将交通灯状态数据抽象成一个数组,利用递归调用依次触发当前状态的定时器。

版本3(过程抽象):利用函数式编程思想,拟定整个交通灯轮询为高阶函数,以设置各个交通灯状态数据的函数为参数,以调用当前交通灯状态的函数为返回值。

版本4(异步):使用 async await编程,更加直观、可读性强。

3、代码实践2:洗牌

(1)错误写法:使用sort方法,在该方法的回调中使用相等概率随机选取升序或降序排列。因为sort方法是两两交换比较,对于n个数,第一个数出现在最后一位的概率为 1/2^(n-1),如果随机排序的概率应该是1/n,  所以不准确。

(2)正确写法:使用for循环,从最后一张牌开始,从0到当前牌的位置随机选取一个数,将该数对于的索引上的牌与当前牌交换。

例如一共n张牌,从第n张牌开始,从0n-1随机选一个数,将第n张牌与该数对应的牌交换,所以第n张牌到任意一个位置上的概率都为1/n;而对于第n-1张牌,从 0n-2随机选一个数,将第n-1张牌与该数对应的牌交换,第n-1张牌到任意一个位置上的概率都为1/(n-1),然而由于第n-1张牌有可能在上一轮与第n张牌交换过,故第n-1张牌在上一轮未被移动过的概率为1-1/n = (n-1)/n,所以第n-1张牌到任意一个位置上的概率都为1/n;

*使用生成器可以解决只需要部分牌结果的问题。

4、代码实践3:拆红包

(1)切西瓜法:选取最大的一个数拆分。较平均

(2)抽牌法: 将金额排成从1到总数递增的数列,从中随机抽取(红包数-1)个数作为"隔板数”,然后将这些“隔板数”和金额总数一起升序排列,将该数列从末尾开始,后一个数减去前一个数得到单个红包金额。

三、课程总结

通过此次课程,我熟悉了JS代码优化的原则和案例,掌握了代码实践案例中解决问题的思路和方法,收获颇丰。