前端小白的成长之路 前端系列—代码性能调优

测试工具

工欲善其事,必先利其器。关于js代码片断的测试,长期以来你们都是经过console.timeEnd相似的方式记录时间来完成的。html

这里也纠正上述方式可靠性,咱们初中学习对照实验时,知道经过控制变量法才能验证某一变量对实验结果的影响。测试代码也应该如此。js所运行的设备和环境,对测试的结果不可谓不大。html5

道理先讲到这,下面安利工具---jsperf,除了UI有点丑,好像没啥槽点!ios

调优方向

1.循环优化

image

2.合并DOM操做

image

除了上例外,引发页面重排和回流的操做,也应该尽可能合并操做。web

触发重排操做axios

1. 页面初始渲染
2. 添加/删除可见DOM元素
3. 改变元素位置 ----- 定位属性及浮动 osition,float
4. 改变元素尺寸(宽、高、内外边距、边框等----- 盒子模型相关属性height,padding ,margin , display ,border-width ,min-height
5. 改变元素内容(文本或图片等)text-align,line-height,vertival-align,overflow , font-size,font-family,font-weight
6. 改变窗口尺寸
7. 获取元素的offsetWidth、offsetHeight、clientWidth、clientHeight、width、height、scrollTop、scrollHeight,请求了getComputedStyle(), 或者 IE的 currentStyle
复制代码

触发回流操做数组

页面中的元素更新外观或风格相关的属性时就会触发重绘,如:background,color,visibility, border-style ,border-radius outline-color,cursor,text-decoration, box-shadowpromise

3. 异步并发优化promise.all

await axios.get('https://www.baidu.com/')
  await axios.get('https://juejin.im')
复制代码

运行时长由两个异步时间相加决定浏览器

const P1 = axios.get('https://www.baidu.com/')
  const P2 = axios.get('https://juejin.im')
  await Promise.all([P1, P2])
复制代码

运行时长由两个异步中较长的时间决定bash

4. 尾递归优化

这里引用阮一峰老师的三句话来描述尾递归并发

咱们知道,函数调用会在内存造成一个"调用记录",又称"调用帧"(call frame),保存调用位置和内部变量等信息。若是在函数A的内部调用函数B,那么在A的调用记录上方,还会造成一个B的调用记录。等到B运行结束,将结果返回到A,B的调用记录才会消失。若是函数B内部还调用函数C,那就还有一个C的调用记录栈,以此类推。全部的调用记录,就造成一个"调用栈"。

尾调用因为是函数的最后一步操做,因此不须要保留外层函数的调用记录,由于调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用记录,取代外层函数的调用记录就能够了。

函数调用自身,称为递归。若是尾调用自身,就称为尾递归。

注意:函数最后return的只能是一个单纯的函数调用,函数调用不能再与其余表达式作计算

const cumulative = (n) => {
  if (n === 1) return 1;
  return cumulative(n - 1) + n;
}
复制代码

优化后:

const cumulative = (n, total) => {
  if (n === 1) return total + 1;
  return cumulative(n - 1, n + total);
}
复制代码

5. 对性能消耗大的操做,适当使用防抖节流

例如在监听resize、scroll、mousemove等操做时

window.addEventListener('scroll',() => {
    let timer ;
    let startTime = new Date();
    return () => {
        let curTime = new Date();
        if(curTime - startTime >= 2000){
            timer = setTimeout(() =>{
                ...
            },500);
            startTime = curTime;
        }

    }
}());
复制代码

你还能作的尝试

突破单线程:webworker

处理密集运算:simd

突破js:WebAssembly

不建议优化的方向

1.原生方法的微观比较

const arr = [];
arr[arr.length] = 1;
arr.push(1);
复制代码

已经忘记是哪位大佬告诉我,数组往末端添加一个元素,前者比后者快。 对于js如今这样的快速发展,就算当下环境是如此,可是只不定哪一个标准就会对其中的方法最优化,探究这样细节的比较,大多数状况下是没有意义的

2.针对单一浏览器或设备的重度优化

观点同上,对单个设备或浏览器的比较优化,却不知其迭代速度远快于js标准,在这上面花时间一样没有必要

参考

《你所不知道的js》 中卷

相关文章
相关标签/搜索