JavaScript手写系列(九)(手写防抖和节流)

46 阅读2分钟

防抖(debounce): 当持续触发事件时, 一定时间段内没有再触发事件, 事件处理函数才会执行一次, 如果设定时间到来之前, 又触发了事件, 就重新开始延时(一般用于实时搜索框)

节流(throttle): 当持续触发事件时, 保证在一定时间内只调用一次事件处理函数, 意思就是说, 假设一个用户一直触发这个函数且每次触发小于既定值, 函数节流会每隔这个时间调用一次(一般用于滚动条事件或者 resize 事件)

区别: 防抖是将多次执行变为最后一次执行, 节流是将多次执行变为每隔一段时间执行

防抖

防抖.png

(百度上面的包浆图片)

防抖的使用场景
  • 登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖
  • 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖
  • 文本编辑器实时保存,当无任何更改操作一秒后进行保存
// 防抖
function debounce(fn, time, immediate) {
    let timer = null
    return function() {
        if (!timer && immediate) {
            fn.apply(this, arguments)   
        }
        if (timer) clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(this, arguments)
        }, time)
    }
}

节流

节流.png

(百度上面的包浆图片)

节流的使用场景
  • 鼠标连续不断地触发某事件(如点击),单位时间内只触发一次;
  • 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断。例如:懒加载;
  • 浏览器播放事件,每个一秒计算一次进度信息等
// 节流
function throttle(fn, time, immediate) {
    let timer = null
    return function() {
        if (immediate) {
            fn.apply(this, arguments)
            immediate = false
        } 
        if (!timer) {
            timer = setTimeout(() => {
                fn.apply(this, arguments)
                timer = null
            }, time)
        }
    }
}
时间戳版节流
// 时间戳
function throttle(fn, time, immediate) {
    let start = Date.now()
    return function() {
        if (immediate) {
            fn.apply(this, arguments)
            immediate = false
        }
        let now = Date.now()
        if (now - start >= time) {
            fn.apply(this, arguments)
            start =  Date.now()
        }
    }
}