面试题 ---- 防抖与节流

参考地址:https://yuchengkai.cn/docs/zh/frontend/#%E9%98%B2%E6%8A%96

参考地址:https://mp.weixin.qq.com/s/Vkshf-nEDwo2ODUJhxgzVA

目录

防抖

 延迟的防抖动函数:

改进版(立即执行的防抖动函数)

节流

使用时间戳的节流方案

使用时间戳+定时器版的节流方案


防抖

当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时,知道用户不在触发后的一定时间内才执行该处理函数。

 延迟的防抖动函数:

该实现思路很简单,就是将执行函数放到一个定时器中,如果在定时器触发之前没有事件执行,那么就触发该执行函数,否则清空定时器

问题:该方法不能立即执行...

//防抖函数        
const debounce = (fn, wait = 1000) => {
            let timer = 0;
            return function (...args) {
                if (timer)
                    clearTimeout(timer)
                timer = setTimeout(() => {
                    fn.apply(this, args);
                }, wait);
            }
 }

测试: 

        function handle(...args) {
            console.log('我被执行了',args);
        }
        let fn=debounce(handle);
        window.addEventListener('scroll',()=>fn(1,2,3));

改进版(立即执行的防抖动函数)

        const debounce = (fn, wait = 1000,immediate=true) => {
            let timer,context,args
            
            //延迟执行函数
            const later=()=>setTimeout(()=>{
                timer=null;
                if(!immediate){
                    fn.apply(context,args);
                    context=args=null
                }
            },wait);

            //这里的函数是每次实际调用的函数
            return function(...params){
                //如果没有创建延迟执行函数则创建
                if(!timer){
                    timer=later();
                    //如果是立即执行函数
                    if(immediate){
                        fn.apply(this,params);
                    }else{
                        context=this
                        args=params
                    }
                }else{
                    //如果已有延迟执行函数,调用的时候则清除原来的并重新设置一个
                    clearTimeout(timer);
                    timer=later()
                }
            }
        }

节流

节流是将多次执行变成每隔一段时间执行,即n秒内只执行一次。

使用定时器简单版

        function throttle(func,delay=1000){
            let canRun=true;
            return function(){
                if(!canRun) return;
                canRun=false;
                setTimeout(() => {
                    func.apply(this,arguments);
                    canRun=true;
                }, delay);
            }
        }

使用时间戳的节流方案

        const debounce=(func,delay=1000)=>{
            let context,args;
            var prev=Date.now();
            return function(...parms){
                var now=Date.now();
                if((now-prev)>=delay){
                    context=this;
                    args=parms
                    func.apply(context,args);
                    prev=Date.now();
                }else{
                    context=args=null;
                }
            }            
        }

使用时间戳+定时器版的节流方案

        const debounce = (func, delay = 1000) => {
            let timer = null;
            let startTime = Date.now();
            return function (...args) {
                let curTime = Date.now();
                let remaining = delay - (curTime - startTime);
                clearTimeout(timer);
                if (remaining <= 0) {
                    func.apply(this, args);
                    startTime = Date.now();
                } else {
                    timer = setTimeout(() => {
                        func.apply(this, args);
                    }, remaining);
                }
            }
        }

 

注:本文只是自我学习的一次总结,若有理解错误,请指出谢谢。

 

 

 

 

 

 

 

你可能感兴趣的:(#,js系列)