资讯专栏INFORMATION COLUMN

JS中的函数去抖与节流

fuchenxuan / 2140人阅读

摘要:上段代码的一个问题是,事件会在定时器结束后被触发,因此会出现一定的延迟,如果想让事件被立即触发,可以使用以下的去抖函数但是,对于去抖来说,在某些场景下是不合适的,因此我们可以使用节流。

参考文章
游戏星人眼中的节流与去抖(很生动)

函数去抖与节流

Debounce:函数去抖就是对于一定时间段的连续的函数调用,只让其执行一次
Throttle:函数节流就是让连续执行的函数,变成固定时间段间断地执行
区别:节流函数不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数。

debounce

浏览器的一些原生事件,在执行时并不是只执行一次,可能会执行很多次,因此需要我们对其加以控制。以scroll举例:

window.onscroll = function() {
    console.log("hello world!");
}

因此,如果执行一些复杂的运算或者DOM操作,对于一些浏览器来说可能会出现崩溃的情况。

去抖debounce实现的效果是:以scroll举例,当scroll执行一次后,会设置一个定时器来控制接下来的一段时间内scroll不会被触发,如果这段时间内又触发了scroll,会在当前时间点重新设置定时器,知道定时器时间结束后才可以被继续触发。因此,debounce保证了一段时间内的连续函数调用,会使其只执行一次。

function debounce(delay, fn) {
    var timer;
    return function() {
        var context = this;
        var args = arguments;
        if(timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(() => {
            fn.apply(context, args);
        }, delay)
    }
}

function print() {
    console.log("hello world!");
}

window.onscroll = debounce(2000, print);

上段代码的一个问题是,事件会在定时器结束后被触发,因此会出现一定的延迟,如果想让事件被立即触发,可以使用以下的去抖函数:

function debounce(delay, fn) {
    var timer;
    return function() {
        var context = this;
        var args = arguments;
        if(timer) {
            clearTimeout(timer);
        }
        var doNow = !timer;
        timer = setTimeout(() => {
            timer = null;
        }, delay);
        if(doNow) {
            fn.apply(context, args);
        }
    }
}

但是,对于去抖来说,在某些场景下是不合适的,因此我们可以使用节流。

throttle

节流可以保证在一段时间内函数必定会触发一次。

节流主要有两种实现:
1.时间戳
2.定时器

// 时间戳实现
function throttle(delay, fn) {
    var prev = Date.now();
    return function() {
        var curr = Date.now();
        if(curr - prev > delay) {
            fn.apply(this, arguments);
            last = curr;
        }
    }
}

// 定时器实现
function throttle(delay, fn) {
    var timer;
    return function() {
        var context = this; // 函数执行上下文
        var args = arguments;
        console.log("1", new Date());
        if(timer) {
            return;
        }
        timer = setTimeout(() => {
            fn.apply(context, args);
            clearTimeout(timer);
            // setTimeout返回一个整数,clearTimeout后也还是整数,因此需要置空,setInterval也是如此
            timer = null;
        }, delay);
    }
}
总结

防止一个事件频繁出发回调函数的方式:
去抖debounce: 一段时间内连续的函数调用,只允许其执行一次。原理是,维护一个定时器,只有定时器结束才可以继续触发事件。
节流throttle: 一段时间内的函数调用,保证事件一定会被执行一次。原理是判断两次执行函数的时间间隔是否大于延迟的时间。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96718.html

相关文章

  • JavaScript 五十问——认真聊一聊抖与节流

    摘要:前言无论是面试还是在讨论浏览器优化过程中,都会涉及到去抖动和节流的问题。总的来说,这二者是一种限制事件触发频率的方式。不同的是,节流会指定事件触发的时间间隔而去抖动会指定事件不触发的时间间隔。 前言 无论是面试还是在讨论浏览器优化过程中,都会涉及到去抖动和节流的问题。总的来说,这二者是一种限制事件触发频率的方式。不同的是,节流会指定事件触发的时间间隔;而去抖动会指定事件不触发的时间间隔...

    chadLi 评论0 收藏0
  • JavaScript 五十问——认真聊一聊抖与节流

    摘要:前言无论是面试还是在讨论浏览器优化过程中,都会涉及到去抖动和节流的问题。总的来说,这二者是一种限制事件触发频率的方式。不同的是,节流会指定事件触发的时间间隔而去抖动会指定事件不触发的时间间隔。 前言 无论是面试还是在讨论浏览器优化过程中,都会涉及到去抖动和节流的问题。总的来说,这二者是一种限制事件触发频率的方式。不同的是,节流会指定事件触发的时间间隔;而去抖动会指定事件不触发的时间间隔...

    EscapedDog 评论0 收藏0
  • JS专题之节流函数

    摘要:一什么是节流节流函数就是让事件处理函数在大于等于执行周期时才能执行,周期之内不执行,即事件一直被触发,那么事件将会按每小段固定时间一次的频率执行。我们通过一个简单的示意来理解节流函数可以用时间戳和定时器两种方式进行处理。 本文共 2000 字,读完只需 8 分钟 上一篇文章讲了去抖函数,然后这一篇讲同样为了优化性能,降低事件处理频率的节流函数。 一、什么是节流? 节流函数(thrott...

    huaixiaoz 评论0 收藏0
  • 小菊花课堂之JS的防抖与节流

    摘要:文章来源详谈防抖和节流轻松理解函数节流和函数防抖函数防抖和节流好啦,今天的小菊花课堂之的防抖与节流的内容就告一段落啦,感各位能耐心看到这里。 前言 陆游有一首《冬夜读书示子聿》——古人学问无遗力,少壮工夫老始成。纸上得来终觉浅,绝知此事要躬行。,其中的意思想必大家都能明白,在学习或工作中,不断的印证着这首诗的内涵。所以,又有了此篇小菊花文章。 详解 在前端开发中,我们经常会碰到一些会持...

    leoperfect 评论0 收藏0
  • 小菊花课堂之JS的防抖与节流

    摘要:文章来源详谈防抖和节流轻松理解函数节流和函数防抖函数防抖和节流好啦,今天的小菊花课堂之的防抖与节流的内容就告一段落啦,感各位能耐心看到这里。 前言 陆游有一首《冬夜读书示子聿》——古人学问无遗力,少壮工夫老始成。纸上得来终觉浅,绝知此事要躬行。,其中的意思想必大家都能明白,在学习或工作中,不断的印证着这首诗的内涵。所以,又有了此篇小菊花文章。 详解 在前端开发中,我们经常会碰到一些会持...

    Yangder 评论0 收藏0

发表评论

0条评论

fuchenxuan

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<