JS—节流与防抖

这篇具有很好参考价值的文章主要介绍了JS—节流与防抖。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、js防抖和节流

在进行窗口的resize、scroll、输出框内容校验等操纵的时候,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常之差。那么为了前端性能的优化也为了用户更好的体验,就可以采用防抖(debounce)和节流(throttle)的方式来到达这种效果,减少调用的频率。

二、为什么滚动scroll、窗口resize等事件需要优化

滚动事件的应用很频繁:图片懒加载、下滑自动加载数据、侧边浮动导航栏等。

在绑定scroll、resize事件时,但它发生的时候,它被触发的频率非常高,间隔很近。在日常开发的页面中,事件中涉及到的大量的位置计算、DOM操作、元素重绘等等这些都无法在下一个scroll事件出发前完成的情况下,浏览器会卡帧。

三、滚动和页面渲染前端性能优化的关系

为什么滚动需要优化?前面提到了事件中涉及到大量的位置计算、DOM操作、元素重绘等等,这些又与页面的渲染有关系,页面渲染又与前端的性能优化有关系?套娃一样,一层套着一层,每一层都联系紧密,每一层都如此平凡且重要。

review一下前端的渲染和优化

web页面展示经历的步骤:js—style—layout—paint—composite,简单回顾一下,在这里不做详细的介绍哦!

网页生成的时候,至少会渲染(Layout+Paint)一次。用户访问的过程中,还会不断重新的重排(reflow)和重绘(repaint),用户scroll行为和resize行为会导致页面不断的进行重新渲染,而且间隔频繁,容易造成浏览器卡帧。

四、防抖Debounce

(1)防抖Debounce情景

①有些场景事件触发的频率过高(mousemove onkeydown onkeyup onscroll)

②回调函数执行的频率过高也会有卡顿现象。 可以一段时间过后进行触发去除无用操作

(2)防抖原理

一定在事件触发 n 秒后才执行,如果在一个事件触发的 n 秒内又触发了这个事件,以新的事件的时间为准,n 秒后才执行,等触发事件 n 秒内不再触发事件才执行。

官方解释:当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。

(3)防抖函数简单实现
    //简单的防抖函数
    function debounce(func, wait, immediate) {
        //定时器变量
        var timeout;
        return function () {
            //每次触发scrolle,先清除定时器
            clearTimeout(timeout);
            //指定多少秒后触发事件操作handler
            timeout = setTimeout(func, wait);
        };
    };
    //绑定在scrolle事件上的handler
    function handlerFunc() {
        console.log('Success');
    }
    //没采用防抖动
    window.addEventListener('scroll', handlerFunc);
    //采用防抖动
    window.addEventListener('scrolle', debounce(handlerFunc, 1000));
(4)防抖函数的演化过程
①this event绑定问题
    //以闭包的形式返回一个函数,内部解决了this指向的问题,event对象传递的问题
    function debounce(func, wait) {
        var timeout;
        return function () {
            var context = this;
            var args = arguments;
            clearTimeout(timeout)
            timeout = setTimeout(function () {
                func.apply(context, args)
            }, wait);
        };
    };
②立即触发问题
    //首次触发执行,再次触发以后开始执行防抖函数
    //使用的时候不用重复执行这个函数,本身返回的函数才具有防抖功能
function debounce(func, wait, immediate) {
    var timeout;
    return function () {
        var context = this;
        var args = arguments;
        
        if(timeout) clearTimeout(timeout);
        // 是否在某一批事件中首次执行
        if (immediate) {
            var callNow = !timeout;
            timeout = setTimeout(function() {
                timeout = null;
                func.apply(context, args)
                immediate = true;
            }, wait);
            if (callNow) {
                func.apply(context, args)
            }
            immediate = false;
        } else {
            timeout = setTimeout(function() {
                func.apply(context, args);
                immediate = true;
            }, wait);
        }
    }
}
③返回值问题
function debounce(func, wait, immediate) {
    var timeout, result;
    return function () {
        var context = this, args = arguments;
        if (timeout)  clearTimeout(timeout);
        if (immediate) {
            var callNow = !timeout;
            timeout = setTimeout(function() {
                result = func.apply(context, args)
            }, wait);
            if (callNow) result = func.apply(context, args);
        } else {
            timeout = setTimeout(function() {
                result = func.apply(context, args)
            }, wait);
        }
        return result;
    }
}
④取消防抖,添加cancel方法
function debounce(func, wait, immediate) {
    var timeout, result;
    function debounced () {
        var context = this, args = arguments;
        if (timeout)  clearTimeout(timeout);
        if (immediate) {
            var callNow = !timeout;
            timeout = setTimeout(function() {
                result = func.apply(context, args)
            }, wait);
            if (callNow) result = func.apply(context, args);
        } else {
            timeout = setTimeout(function() {
                result = func.apply(context, args)
            }, wait);
        }
        return result;
    }
    debounced.cancel = function(){
        cleatTimeout(timeout);
        timeout = null;
    }
    return debounced;
}
五、节流Throttle
(1)节流Throttle情景

①图片懒加载

②ajax数据请求加载

(2)节流原理

如果持续触发事件,每隔一段时间只执行一次函数。

官方解释:当持续触发事件时,保证一定时间段内只调用一次事件处理函数。

(3)节流实现—时间戳和定时器
  • 时间戳
    var throttle = function (func, delay) {
        var prev = Date.now()
        return function () {
            var context = this;
            var args = arguments;
            var now = Date.now();
            if (now - prev >= delay) {
                func.apply(context, args);
                prev = Date.now();
            }
        }
    }

    function handle() {
        console.log(Math.random());
    }
    window.addEventListener('scroll', throttle(handle, 1000));
  • 定时器
    var throttle = function (func, delay) {
        var timer = null;
        return function () {
            var context = this;
            var args = arguments;
            if (!timer) {
                timer = setTimeout(function () {
                    func.apply(context, args);
                    timer = null;
                }, delay);
            }
        }
    }

    function handle() {
        console.log(Math.random());
    }
    window.addEventListener('scroll', throttle(handle, 1000))
(4)节流函数的演化过程
①时间戳触发
//在开始触发时,会立即执行一次; 如果最后一次没有超过 wait 值,则不触发
function throttle(func, wait) {
    var context, args;
    var previous = 0; // 初始的时间点,也是关键的时间点

    return function() {
        var now = +new Date();
        context = this;
        args = arguments;
        if (now - previous > wait) {
            func.apply(context, args);
            previous = now;
        }
    }
}
②定时器触发
//首次不会立即执行,最后一次会执行,和用时间戳的写法互补。
function throttle(func, wait){
    var context, args, timeout;
    return function() {
        context = this;
        args = arguments;
        if(!timeout) {
            timeout = setTimeout(function(){
                func.apply(context, args);
                timeout = null;
            }, wait);
        }
    }
}
③结合时间戳和定时器
function throttle(func, wait) {

    var timer = null;
    var startTime = Date.now();  

    return function(){
        var curTime = Date.now();
        var remaining = wait-(curTime-startTime); 
        var context = this;
        var args = arguments;

        clearTimeout(timer);

        if(remaining<=0){ 
            func.apply(context, args);

            startTime = Date.now();

        }else{
            timer = setTimeout(fun, remaining);  // 如果小于wait 保证在差值时间后执行
        }
    }
}
六、节流防抖总结

防抖:原理是维护一个定时器,将很多个相同的操作合并成一个。规定在delay后触发函数,如果在此之前触发函数,则取消之前的计时重新计时,只有最后一次操作能被触发。

节流:原理是判断是否达到一定的时间来触发事件。某个时间段内只能触发一次函数。

区别:防抖只会在最后一次事件后执行触发函数,节流不管事件多么的频繁,都会保证在规定时间段内触发事件函数。文章来源地址https://www.toymoban.com/news/detail-401090.html

到了这里,关于JS—节流与防抖的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【JS进阶】防抖与节流

    1.防抖 1.1 为什么要防抖? 在项目中,有的操作是 高频触发 的,但是其实触发一次就好了,比如我们短时间内多次缩放页面,那么我们不应该每次缩放都去执行操作,应该只做一次就好。再比如说监听输入框的输入,不应该每次都去触发监听,应该是用户完成一段输入后再进

    2024年02月09日
    浏览(42)
  • js实现防抖(debounce)与节流(throttle)

    一句话概括:防抖是给定一个时间周期,如果触发事件的周期小于该时间(也就是触发过快),则不会触发事件。 举个例子:我给定的时间周期是1s,如果我在触发第一次事件后1s内触发该事件,则重新开始计时,直到触发周期大于1s才会执行事件的方法。 一句话概括:节流

    2023年04月23日
    浏览(37)
  • 【js】防抖和节流的使用场景和区别:

    一、防抖 (多次触发 只执行最后一次) 作用: 高频率触发的事件,在指定的单位时间内,只响应最后一次,如果在指定的时间内再次触发,则重新计算时间 防抖类似于英雄联盟回城6秒,如果回城中被打断,再次回城需要再等6秒 二、节流 (规定时间内 只触发一次) 作用:

    2024年02月10日
    浏览(39)
  • JS手写防抖和节流函数(超详细版整理)

    防抖(debounce) :每次触发定时器后,取消上一个定时器,然后重新触发定时器。防抖 一般用于用户未知行为的优化 ,比如搜索框输入弹窗提示,因为用户接下来要输入的内容都是未知的,所以每次用户输入就弹窗是没有意义的,需要等到用户输入完毕后再进行弹窗提示。

    2024年02月04日
    浏览(37)
  • 前端面试题-js-new关键字-this指向-js事件流-防抖节流

    1.创建一个简单的空对象 2.原型的绑定,确定对象O的原型链 3.绑定this对象为O,传入参数;执行Person构造函数,进行属性和方法的赋值操作 4.返回结果 普通函数的this指向 函数的this指向有一个基本的原则,谁调用的函数,函数的this就指向谁,否则指向全局 箭头函数的this指向

    2024年01月25日
    浏览(49)
  • Vue 3 中的极致防抖/节流(含常见方式防抖/节流)

    各位朋友你们好呀。今天是立春,明天就是正月十五元宵节了,这种立春 + 元宵相隔的时候,可是很难遇到的,百年中就只有几次。在这提前祝大家元宵快乐。 今天给大家带来的是 Vue 3 中的极致防抖/节流(含常见方式防抖/节流) 这篇文章,文章中不仅会讲述原来使用的防

    2024年02月01日
    浏览(45)
  • 前端优化 ----防抖 节流

    如果一个事件在短时间内连续触发,则只去执行最后一次。 控制频率 实现方式:每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法 缺点:如果事件在规定的时间间隔内被不断的触发,则调用方法会被不断的延迟 使一个函数在固定时间内只执行一次。控制

    2024年02月04日
    浏览(41)
  • 前端刷题-防抖节流

    在实际的开发过程中,一般会使用lodash自有的debounce函数和throttle函数对所要防抖/节流的函数进行包裹。例如

    2024年02月10日
    浏览(43)
  • 防抖,节流

    防抖(debounce):类似法师技能读条,读条没完再按技能就会重新读条,在触发后的n秒内只会执行一次,若在这n秒内重复触发则重新计算 节流(throttle):连续发生的事件在n秒内只执行一次函数 【前端面试必问】—常见的机试题—瀑布流_哔哩哔哩_bilibili 防抖和节流(详解) 使用

    2024年02月12日
    浏览(44)
  • 节流&防抖

    节流:wait时间内只能执行一次func 防抖:触发后延迟wait秒调用func 代码对比:(建议自己手敲一遍,不要养成直接cv的坏习惯) 节流: 其中的apply函数是    apply() 是 JavaScript 函数的一个方法,它用于调用函数并设置函数内部 this 的指向。 在 throttle() 函数中, func 是传

    2024年02月07日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包