JavaScript 防抖函数是一种常见的优化技术,它可以在用户连续触发某个事件时,只执行最后一次触发的操作,以避免频繁的操作。
例如,当用户在搜索框中连续输入字母时,防抖函数可以延迟执行搜索操作,只在用户停止输入一段时间后才真正执行搜索。 JavaScript 防抖函数的原理是利用了定时器和闭包的特性。
原理
触发事件 -> 设置计时器 -> 前面有计时器清除(中断时间处理函数的运行) -> 调用
当防抖函数第一次被调用时,它会记录当前的上下文和参数,并设置一个计时器,计时器的时间间隔由防抖函数的第二个参数 delay 决定。如果在这段时间内,防抖函数再次被调用,它会清除之前的计时器,并重新设置一个新的计时器。因此,在 delay 毫秒内连续调用防抖函数时,计时器会被不断地清除和设置,直到最后一次调用。
当最后一次调用发生时,计时器会等待 delay 毫秒后才执行防抖函数的真正操作。因此,只有最后一次调用会被真正执行,前面的调用都会被清除,从而避免了频繁的操作。
闭包的作用在于,防抖函数内部返回一个新的函数,该函数可以访问防抖函数内部的变量。这样,在新的函数被连续调用时,它可以访问到之前设置的计时器 ID,并清除它,从而实现防抖的效果。
图解
细节处理
由于函数实现返回函数里面执行的,所以this指向window
而this应该指向函数调用者dom对象, this 被 newHandler传入debounce,记录this的值
将arguments是事件对象,使用apply将函数内部this指向为dom对象,将arguments事件对象传入参数,
在这个例子中,当 newHandler 函数作为事件监听函数被调用时,this 值确实是绑定了事件的 DOM 元素。然后 newHandler 函数内部调用了 debounce 函数,此时 debounce 函数内部的 this 值也会变成 DOM 元素。
所以,debounce 函数内部的 this 值就是绑定了事件的 DOM 元素。在 debounce 函数内部,我们将这个值保存到了 curThis 变量中,然后在闭包函数内部使用了 fn.apply(curThis, args) 将其传递给了回调函数。