最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 面试题:什么是防抖节流?说一下它们的区别

    正文概述 掘金(邑大学子_)   2021-02-10   766

    面试题:什么是防抖节流?说一下它们的区别

    一、前言

    浏览器的 resizescrollkeypressmousemove 等事件在触发时,会极速地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能

    为了优化体验,需要对这类事件进行调用次数的限制,对此我们可以采用debounce(防抖)和throttle(节流)的方式来减少调用频率,同时又不影响实际效果

    下面来看一张图:

    面试题:什么是防抖节流?说一下它们的区别

    从上图中,可以看到:

    • 防抖是一段时间后只执行一次
    • 节流是在固定的频率执行

    二、防抖(debounce)

    防抖是当连续触发事件的时候,事件不会持续触发,当一定时间内没有触发事件后,事件函数才会执行

    例如:就好像在百度搜索时,每次输入之后都有联想词弹出,这个控制联想词的方法就不可能是输入框内容一改变就触发的,它一定是当你结束输入一段时间之后才会触发

    下面来举个例子

    // 普通方案
    let container = document.getElementById('container');
    
    function getUserAction() {
        container.innerHTML = count++;
    };
    container.onmousemove = getUserAction;  // 鼠标移动会一直触发getUserAction函数
    
    // 优化后的方案
    function debounce(func, wait) {
        let timeout;
    
        return function () {
            let context = this; // 保存this指向
            let args = arguments; // 拿到event对象
    
            clearTimeout(timeout)
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
    }
    container.onmousemove = debounce(getUserAction, 1000); // 1s内不再触发后才会执行事件
    

    这里作一下分析:

    • mousemove事件上绑定处理函数,这时 debounce 函数会立即调用,实际上绑定的函数是 debounce 函数内部返回的函数
    • 每一次事件被触发,都会清除当前的 timeout 然后重新设置超时调用
    • 只有在最后一次触发事件,才能在 wait 时间后执行

    我们也可以为 debounce 函数加一个参数,可以选择是否立即执行函数

    function debounce(func, wait, immediate) {
    
        let timeout;
    
        return function () {
            let context = this;
            let args = arguments;
    
            if (timeout) clearTimeout(timeout); // timeout 不为null
            if (immediate) {
                let callNow = !timeout; // 第一次会立即执行,以后只有事件执行后才会再次触发
                timeout = setTimeout(function(){
                    timeout = null;
                }, wait)
                if (callNow) func.apply(context, args)
            }
            else {
                timeout = setTimeout(function(){
                    func.apply(context, args)
                }, wait);
            }
        }
    }
    

    三、节流(throttle)

    节流是当持续触发事件时,保证一段时间内,只调用一次事件处理函数

    例如:浏览器播放事件,每隔一秒计算一次进度信息。

    节流的实现方式可以分为两种:

    第一种通过时间戳来实现,用一个变量保存上一次执行的时间,每次触发事件时生成一个时间戳,与上一次执行时间比较,如果大于给定的时间,则执行函数

    function throttle(func, wait) {
        let context, args;
        let previous = 0;
    
        return function() {
            let now = +new Date();
            context = this;
            args = arguments;
            if (now - previous > wait) {
                func.apply(context, args);
                previous = now;
            }
        }
    }
    

    第二种通过定时器来实现,设置一个变量绑定一个定时器,通过if判断定时器是否存在,如果存在就不执行,当定时器执行时把变量置为null,这样在下一次触发事件时就可以设置定时器了

    function throttle(func, wait) {
        var timeout;
        var previous = 0;
    
        return function() {
            context = this;
            args = arguments;
            if (!timeout) {
                timeout = setTimeout(function(){
                    timeout = null;
                    func.apply(context, args)
                }, wait)
            }
    
        }
    }
    

    比较这两种方法:

    • 第一种事件会立刻执行,第二种事件会在 n 秒后第一次执行
    • 第一种事件停止触发后没有办法再执行事件,第二种事件停止触发后依然会再执行一次事件

    四、区别

    防抖和节流的作用都是防止函数多次调用

    区别在于,假设一个用户一直触发这个函数,且每次触发函数的间隔小于wait(参数wait),防抖的情况下只会调用一次,而节流的情况会每隔一定时间调用函数

    五、结束语

    如果觉得这篇文章对你有帮助,可以伸出你的小手,为这篇文章点个赞

    我是前端路上一位新晋的萌新,怀着学习的态度,怀着认识各位同伴的心态,把自己的知识分享出来,除了让自己对知识认知更加巩固,也希望大家能够通过我写的文章学到一点微薄的知识,如果知识内容有误,可以在评论区或者下面公众号告诉我,我会立刻更改

    最后,我也创建了一个 【前端收割机】的公众号,希望大家可以关注一波,里面的文章都是掉头发之作


    起源地下载网 » 面试题:什么是防抖节流?说一下它们的区别

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元