节流函数

在我们开发的JavaScript操作中,有时候需要操作到页面的dom结构,同时JavaScript不提倡多次直接操作dom结构是因为操作dom结构会带来性能的丢失。如果像onresize这样的函数多次操作dom结构可能会导致浏览器奔溃,所以为了绕开这个问题,我们需要使用定时器对函数进行节流。

例如一个onresize函数

  1. window.onresize = function(){
  2. var div = document.getElementById('Div');
  3. div.style.height = div.offsetWidth + 'px';
  4. }

如果不断改变浏览器的大小,那么这个函数将会不断地执行、重绘,浏览器性能也随之下降。
我们就需要使用定时器给这个函数一定的时间延迟

  1. function resizeDiv(){
  2. var div = document.getElementById('Div');
  3. div.style.height = div.offsetWidth + 'px';
  4. }
  5. function throttle(fn, delay, scope) {
  6. let timer;
  7. return function () {
  8. let context = scope || this, args = arguments;
  9. if (!timer) {
  10. timer = setTimeout(function () {
  11. fn.apply(context, args);
  12. timer = null;
  13. }, delay)
  14. }
  15. }
  16. }
  17. 作者:JarvisJie
  18. 链接:https://juejin.im/post/5c00f7fe51882516be2ee2fc
  19. 来源:掘金
  20. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  21. window.onresize = function(){
  22. thorttle(resizeDiv());
  23. }
els[2].addEventListener('scroll', throttle(function handle() {
        console.log(Date.now(),', 执行滚动事件!(函数节流) count3=', ++count3);
    }, 200));

函数防抖

function debounce(fn, delay, scope) {
    let timer = null;
    // 返回函数对debounce作用域形成闭包
    return function () {
        // setTimeout()中用到函数环境总是window,故需要当前环境的副本;
        let context = scope || this, args = arguments;
        // 如果事件被触发,清除timer并重新开始计时
        clearTimeout(timer);
        timer = setTimeout(function () {
            fn.apply(context, args);
        }, delay);
    }
}

作者:JarvisJie
链接:https://juejin.im/post/5c00f7fe51882516be2ee2fc
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

//调用
window.onresize = throttle(myFunc,1000);

上诉的代码说明,调整大小的功能被放入了一个叫做 resizeDiv()的单独函数中。然后 onresize 事件处理 程序调用 throttle()并传入 resizeDiv 函数,而不是直接调用 resizeDiv()。多数情况下,用户是感觉不到变化的,虽然给浏览器节省的计算可能会非常大。

简单来说,实现的功能就是在一定的时间内,限制某个函数只执行一次。

 els[0].addEventListener('scroll', function handle() {
        console.log('普通滚动事件!count1=', ++count1);
    });
    els[1].addEventListener('scroll', debounce(function handle() {
        console.log('执行滚动事件!(函数防抖) count2=', ++count2);
    }, 200));

作者:JarvisJie
链接:https://juejin.im/post/5c00f7fe51882516be2ee2fc
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

总结

函数节流和函数防抖的基本区别就是函数再次执行是是否清空上次的函数

  • 函数节流执行时,只会添加一个定时器,类似于延时执行,执行完毕之后将会清空这个timer,若timer还没有清空,那么将不会重新覆盖掉
  • 函数防抖则是在函数执行的时候直接清空掉timer,并且重新赋值一个,其目的就是为了只在最后一次定时器完成时才执行方法