【面试题】防抖和节流

【面试题】防抖和节流



1. 防抖和节流

概念

  防抖:在一定的时间间隔内,将多次的触发变成一次触发,类似游戏中的回城,你一直触发回城事件,但是最终只能执行一次,等到回城时间一到就回家了

  节流:减少在一段时间内的频率,类似游戏中的技能CD,在指定的时间内只能使用一次技能


1. 防抖

1.1 普通防抖

/*
    防抖函数
    参数一:需要防抖的函数
    参数二:延时时间
*/

function debounce (fun,delay){
    let timeout = null
    return function(){
        // 如果有值则清除定时器
        if(timeout)
        {
            clearTimeout(timeout)
        }
        // 如果没有值则开一个定时器
        timeout = setTimeout(() => {
            /*
                1. 这里使用箭头函数将this的指向外部
                2. 补充知识点arguments(实参列表) ,每个实参
                列表对应自己内部函数,只有在函数的内部才会产生
                实参列表,在这里使用箭头函数,将箭头函数内部的指向arguments,
                指向外部
             */
            fun.apply(this,arguments)
        }, delay);
    }
}


function request(e){
     console.log('发送请求');
     console.log(this);
     /*
        e是什么时候传进来的?
        当window调用该函数的时候将实参传进来
      */
     console.log(e);
}

let btn = document.querySelector('button')
btn.addEventListener('click',debounce(request,500))


1.2 防抖升级

/*
    防抖函数
    参数一:需要防抖的函数
    参数二:延时时间
*/

function debounce (fun,delay){
    let timeout = null
    return function(){
        // 如果有值则清除定时器
        // 需要注意:清除定时器,不代表把值给清除了
        if(timeout)
        {
            clearTimeout(timeout)
        }else{
            // 第一次立即执行,后面触发效果和普通防抖一样
            fun.apply(this,arguments)
        }       

         // 如果没有值则开一个定时器
         timeout = setTimeout(() => {
            /*
                1. 这里使用箭头函数将this的指向外部
                2. 补充知识点arguments(实参列表) ,每个实参
                列表对应自己内部函数,只有在函数的内部才会产生
                实参列表,在这里使用箭头函数,将箭头函数内部的指向arguments,
                指向外部
            */
            fun.apply(this,arguments)
        }, delay);
    }
}


function request(e){
     console.log('发送请求');
     console.log(this);
     /*
        e是什么时候传进来的?
        当window调用该函数的时候将实参传进来
      */
     console.log(e);
}

let btn = document.querySelector('button')
btn.addEventListener('click',debounce(request,1000))

1.3 新增防抖参数(立即执行)

/*
    防抖函数
    参数一:需要防抖的函数
    参数二:延时时间
    参数三:是否开启立即执行
    注意:这里的立即执行指的是第一次点击时
    不进行延时,而这里的第一次指的是每次延时后
    再次点击都算第一次
*/

function debounce (fun,delay,immediate=false){
    let timeout = null
    return function(){
        // 如果有值则清除定时器
        // 需要注意:清除定时器,不代表把值给清除了
        if(timeout)
        {
            clearTimeout(timeout)
        }

        // 判断是否开启立即执行
        if(immediate)
        {
            // 第一次进来timeout值为null,取反为真
            let first = !timeout
            if(first)
            {
                fun.apply(this,arguments)
            }
            timeout = setTimeout(() => {
                // 延时过后恢复timeout的值,让它能够调用函数
                timeout = null
            }, delay);
        }else
        {
            // 如果没有值则开一个定时器
            timeout = setTimeout(() => {
                /*
                    1. 这里使用箭头函数将this的指向外部
                    2. 补充知识点arguments(实参列表) ,每个实参
                    列表对应自己内部函数,只有在函数的内部才会产生
                    实参列表,在这里使用箭头函数,将箭头函数内部的指向arguments,
                    指向外部
                */
                fun.apply(this,arguments)
            }, delay);
        }
    }
}


function request(e){
     console.log('发送请求');
     console.log(this);
     /*
        e是什么时候传进来的?
        当window调用该函数的时候将实参传进来
      */
     console.log(e);
}

let btn = document.querySelector('button')
btn.addEventListener('click',debounce(request,1000,true))

2. 节流

2.1 第一种写法

function throttle (fun,delay){
    let previous = 0
    return function(){
        let current = new Date()
        // 大于延时的时间,就表示技能CD已经好了可以用了
        console.log(current - previous);
        if(current - previous > delay)
        {
            fun.apply(this,arguments)
            // 更新时间
            previous = current
        }
    }

}

function request(e){
     console.log('发送请求');
     console.log(this);
     /*
        e是什么时候传进来的?
        当window调用该函数的时候将实参传进来
      */
     console.log(e);
}

let btn = document.querySelector('button')
btn.addEventListener('click',throttle(request,1000))

2.2 第二种写法

function throttle (fun,delay){
    let flag = true
    return function(){
        if(flag)
        {
            fun.apply(this,arguments)
            flag = false
            setTimeout(() => {
                // 延时时间一到恢复技能使用权
                flag = true
            }, delay);
        }
    }
}

function request(e){
     console.log('发送请求');
     console.log(this);
     /*
        e是什么时候传进来的?
        当window调用该函数的时候将实参传进来
      */
     console.log(e);
}

let btn = document.querySelector('button')
btn.addEventListener('click',throttle(request,2000))

总结

以上就是今天要讲的内容,希望对大家有所帮助!!!

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值