性能优化和调试技巧
1性能优化
1.1防抖
-
痛点:Js中的函数绝大多是由用户主动调用触发的,但是在一些少数情况下函数的触发不是由用户直接控制的,在这种情况下可能会被非常频繁地调用,从而造成性能问题。例如鼠标的mousemove事件,如果需要实现一个拖拽功能,就需要持续监听 mousemove事件,如果不加以控制,即使鼠标移动的距离很小,回调事件的触发次数仍然十分巨大。有比如window的onresize事件,当浏览器窗口大小被拖动而改变尺寸的时候这个事件会被一直触发,对性能造成巨大的消耗。
-
实现原理:所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
-
代码实现
/* 防抖代码 */ function debounce(fun, delay) { let timeout = null; return function(e) { clearTimeout(timeout); timeout = setTimeout(() => { fun(); }, delay*1000) } } /* 处理函数 */ function handle() { ... } //监听窗口滚动事件 window.addEventListener('scroll', debounce(handle, 5));
1.2节流
-
痛点:同上
-
实现原理:函数节流的实现原理和函数防抖略有不同,函数节流保证了回调函数在规定时间内只执行一次。但两者都是为了限制回调函数的执行频次,以优化函数触发频率过高导致的浏览器性能下降问题。
-
代码实现
/* 节流函数 */ function throttle(fun, delay) { let run = true // 设置节流阀是节流实现的关键 return function() { if (!run) { return; } run = false; setTimeout(() => { fun(); run = true; }, delay*1000) } } /* 处理函数 */ function handle() { ... } //监听窗口滚动事件 window.addEventListener('scroll', throttle(handle, 5));
1.3重绘和重排
-
浏览器的渲染机制:HTML会被HMTL解析器解析成DOM Tree。css会被css解析器解析成CSSOM Tree(并行解析),两者解析完成后被合并到一起,形成渲染树。
-
概念 1)重排:也叫回流,在DOM的大小,位置进行修改后,浏览器要重新计算元素的这些几何属性,这就是重排。(一个子元素的集合属性发生改变,直接影响了其父元素、兄弟元素以及向上追溯到的很多祖先元素,浏览器也要重新渲染与被修改元素相关联的其他元素)。重排几乎是无法避免的,页面的首次渲染、字体大小和数量的修改、伪类的激活、删除可见的DOM元素、改变浏览器窗口的大小等都会引发重排。 2)重绘:对DOM的样式进行修改,如color和background-color,浏览器不需要重新计算几何属性,直接绘制被修改元素的新样式,就是重绘。
-
优化 1)必要性:整个在浏览器的渲染过程中(页面初始化,用户行为改变界面样式,动画改变界面样式等)重排和重绘会大大影响web性能。重绘和重排的开销是非常昂贵的,如果我们不停的在改变页面的布局,就会造成浏览器耗费大量的开销在进行页面的计算,这样的话,我们页面在用户使用起来,就会出现明显的卡顿。 2)实现方法: ①、减少offsetTop、offsetLeft、scrollTop、scrollLeft、clientTop、clientLeft等属性的使用。 ②、减少DOM操作
const el = document.querySelector('.el'); el.style.borderLeft = '1px'; el.style.borderRight = '1px'; el.style.padding = '1px'; // 以上操作会引起三次重排③、批量修改DOM元素 ④、减少使用CSS表达式
1.4代码细节
- 慎用全局变量(全局变量定义在全局上下文,沿着作用域链查找全局变量会浪费时间,降低性能)。可以用缓存全局变量的方法优化此问题。
- 通过原型链给实例原型新增方法,减少实例在内存中占用的空间。
- 减少闭包的使用,闭包使用不当会造成内存泄露。
- 延迟不必要的js首屏加载。
- 合理使用事件委托。 ......
2调试工具
- chrome开发者工具
- firefox插件firebug
- IE开发者工具 ......