防抖函数中的闭包

50 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第27天

防抖函数中的闭包

这里不介绍防抖函数原理,只单纯在其语法上进行分析,如有错误还请指出 不明白闭包是什么?请移步->简单理解:闭包是什么? - 掘金 (juejin.cn)

debounce(func, delay) {
    let timer = null
    return function(...args){
        if(timer) clearTimeout(timer)
        timer = setTimeout(()=>{
            func.apply(this, args)
        }, delay)
    }
}

闭包指的是那些引用了另一个函数作用域中变量的函数。

很明显,在防抖函数中,返回值是一个函数,在这个被返回的函数中调用了debounce函数作用域中的变量timer

我们在使用防抖函数时:

//直接赋值给一个变量,func是要进行防抖操作的方法,delay是延迟时间
let foo = debounce(func, delay)

我们调用debounce函数,定义了foo来接收它的返回值,现在,foo就指向debounce返回的函数了:

let foo = function(...args){
            if(timer) clearTimeout(timer)
            timer = setTimeout(()=>{
                func.apply(this, args)
            }, delay)
        }

与以上定义形式的效果相似,但不同的是,使 foo = debounce(func, delay) 让foo拥有了debounce的函数作用域,可以让它不论第几次执行,都可以访问到同一个debounce中的timer变量,方便我们每次调用时进行定时器的清除。

//添加监听,方法为防抖函数,要加括号和参数
element.addEventListener(event, debounce(func, delay))
//添加监听,方法为正常函数,这里是不加小括号的
element.addEventListener(event, func)

一般我们使用addEventListener,函数只写名字而不写小括号,是因为要将其本身传给他,若加了小括号,传给它的就是其返回值,我们这里加小括号,就是为了将debounce的返回值,也就是它内部的匿名函数传给它,之后每次事件发生,监听器都会自动调用debounce中的匿名函数,而不是debounce本身,这也是容易混淆的一点