前端进阶(1) -- 函数防抖

2019-03-28 00:00:00

函数防抖的背景、原理和实现

前言

在本文开始前,你可以先想想前端语言有哪些特点。没错了,回调就是其中之一。在前端开发中不可避免得会遇到需要频繁触发事件回调的情况:

  • window的resize、scroll
  • 元素的click、mouseover、mousedown
  • keyup、keydown 等等情况

让我猜猜你们通常的做法是不是直接为这些事件添加回调,比如:

<div onclick='clickFn'>点点我</div>

function clickFn () {
    ...
}

咋一看没问题呀,然而实际上,你还是 too young too simple 呀!那么问题出在哪了呢? 按照上面的写法,我频繁点击div,那么就会不断触发click事件,当clickFn函数简单时,倒是没啥问题,当clickFn函数执行内容复杂时,会发生什么?肯定会发生浏览器卡死呀,这肯定是大家想要的,其实很多时候我们也不需要每一次点击都执行一次回调,只需要在频繁点击后执行最后一次的回调即可,怎么做呢?接下来引出今天的主角 -- 函数防抖。

防抖

原理:防抖的实质就是:"取消预约 - 重新预约" 的过程。 触发事件时,如果直接执行,那就控制不了了,所以需要延迟执行,在延迟的这段时间如果重新触发,那就取消再重新设置延迟。

效果:多次触发,只执行最后一次

上代码:注意理解this、args 的用意

function debounce(fn, wait) {
    let timer
    return function () {
        let args = arguments
        clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(this, args)
        }, wait)
    }
}
取消

使用防抖之后,会在执行前存在延时,如果在这个延时区间内我们想要提前取消回调,怎么办?那就再完善一下上面的代码

function debounce(fn, wait) {
    let timer
    let debouncedFn = function () {
        let args = arguments
        clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(this, args)
        }, wait)
    }
    // 添加取消功能
    debouncedFn.cancel = function () {
        clearTimeout(timer)
        timer = null
    }
    return debouncedFn
}

总结

本文通过防抖解决了前端常见的函数频繁执行的问题。最后说一句,切勿眼高手低,要用思想驱动行动,用行动发现问题,再用问题提升自己,一步亦趋!

Gitalking ...

Markdown is supported

Be the first guy leaving a comment!