你真的已经理解防抖和节流了吗?

前言

如果经常在一些技术社区"散步"的话,函数的"防抖"和"节流"这两个词被提到的频率还是挺高的,但是做了一年的开发,却没有在自己写的项目中用到,还是要好好反思一下。痛定思痛,好好学习。

防抖(debounce)

原理🍖

事件执行n秒后再执行回调,如果在这n秒内再次被触发,则n秒重新计算。

应用场景🍔
  • 搜索框: 用户输入完关键词再去触发搜索行为;
  • window的resize事件:用户调整大小结束之后再去触发相应的操作;
效果预览
  • 防抖前
// 代码预览
<input id="debounce"></input> 搜索框

function search(e) {
    console.log('开始搜索' , e.target.value)
}
const de = document.getElementById('debounce')
de.addEventListener('input', search)
  • 防抖后

// 代码预览
<input id="debounce"></input> 搜索框

function search(e) {
    console.log('开始搜索' , e.target.value)
}

function debounce(fn, delay) {
    let ts = null
    console.log('debounce')
    return function() {
        clearTimeout(ts)
        ts = setTimeout(() => {
            fn.apply(this, arguments)
        }, delay)
    }
} 
const de = document.getElementById('debounce')
de.addEventListener('input', debounce(search, 1000))
是真的理解了吗?(思考)👺
  • 为什么debounce这个字符串只是打印了一次?

addEventListener绑定的时候,用的是debounce这个函数的返回值,其实对比一下防抖前就很容易理解了。

  • 为什么fn.apply(this, arguments),而不能是fn()?

其实在当前这个程序中,我们可以用fn(…argruments)来替换fn.apply(this, arguments),因为我们在search中也没有用到this。当然也可以用call,fn.call(this, …arguments)

  • setTimeout中的函数为什么用箭头函数?

箭头函数没有this,如果不用箭头函数,this可就指向了setTimeout,就的换个写法

function debounce(fn, delay) {
    let ts = null
    console.log('debounce')
    return function() {
        clearTimeout(ts)
        const context = this, args = arguments
        ts = setTimeout(function() {
            fn.apply(context, args)
        }, delay)
    }
} 

节流(throttle)

原理🍖

事件执行n秒后再执行回调,如果再这n秒内再次被触发,则忽略。通俗点讲,就想王者荣誉中的英雄技能的冷却时间,没到冷却的时间,你怎么点都是没有效果的。

应用场景
  • 表单提交: 多次点击提交按钮
  • 滚动条scroll事件:当滚动条滑动到底部的时候再去请求其他数据
效果预览(节流前的效果在前面以及体现,我们直接看节流后的效果)

// 代码预览🍔
function throttle(fn, delay) {
    let ts = null
    return function() {
        if (!ts) {
            ts = setTimeout(() => {
                fn.call(this, ...arguments)
                ts = null
            }, delay)
        }
    }
}
问题考虑👺
  • 往往我们希望的是,点击按钮需要立即执行,第一次之后再做节流,让我们对代码做一些优化
function throttle(fn, delay) {
    let ts = null
    let first = true
    return function() {
        if (first) {
            fn.call(this, ...arguments)
            first = false
        }
        if (!ts) {
            ts = setTimeout(() => {
                fn.call(this, ...arguments)
                ts = null
            }, delay)
        }
    }
} 
  • 现在来看一下效果

总结与思考

  • 防抖和节流看似简单的两个个函数,却涵盖了很多的基础知识点,我们不妨思考一下:闭包、函数作用域、this指向等问题
  • 思考在我们的项目中为什么没有用到,之后是否作为优化添加上这两个效果。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值