节流
解决的问题:
假设有一个事件会频繁触发,比如鼠标移动的时候会频繁鼠标的移动事件,这会消耗太多性能。要解决这个问题,你可以通过节流的方式,控制触发的间隔,从而进行性能的优化。
也就是说:节流就是同一个函数被事件触发之后执行,必须间隔一段时间。事件可以触发很多次,但是执行的频率是被控制的。
实现目标:实现一个函数,这个函数的参数有两个:一个是将要执行的方法fn;第二个是这个fn间隔多久才执行一次,也就是延迟时间delay(单位是ms)。
实现思路:执行fn的时候,查看是否有计时器,如果有那么就不执行fn(因为时间到了只会,fn会自动触发),如果没有计时器,那么就添加一个计时器并把时间设置为delay的值
//这个函数传入一个函数fn,以及一个延迟执行的时间(默认是100毫秒),实现目标:fn函数要在100ms的间隔才触发一次。
//思路:执行fn的时候,查看是否有计时器,如果有那么就不执行fn(因为时间到了只会,fn会自动触发),如果没有计时器,那么就添加一个计时器并把时间设置为delay的值。
function throttle(fn, delay = 100) {
let timer = null
return function(){
if(timer) {
return
}
timer = setTimeout(() => {
//this指向的是div对象,而arguments指向是函数本身的类数组类型的参数列表,而函数本身由事件监听器调用,所以arguments[0]存的是事件对象。
fn.apply(this, arguments)
timer = null
},delay)
}
}
let div = document.querySelector('.throttle')
div.addEventListener('click', throttle(function(){}),200)
如果获取了一个节点div,并通过添加事件监听器的方式来添加节流函数,注意this始终指向调用该事件处理器的节点本身
防抖
防抖,意思是每当事件触发,处理函数就会在间隔触发点之后的一段时间过后才会执行。 假定这段时间被指定为200毫秒,那么处理函数就会在200毫秒之后才执行。如果这段时间内又触发了事件,那么间隔时间将会从新的事件之后开始计算。
解决的问题:假设有一个事件会频繁触发,但是只关注最后的结果,那么应该使用防抖的方式,尽量去获取最后的结果,而不对中间值进行任何处理。比如文本输入框里的内容完成之后要进行内容检索,但是在完成之前,内容总是在不停的变化,此时就适合使用防抖来进行优化。
实现目标:实现一个函数,这个函数的参数有两个:一个是触发事件时,将要执行的方法fn;第二个是这个fn在多久之后才能执行,也就是延迟时间,取名delay(单位是ms)
实现思路:由于不关注中间结果,只关注最后的状态,所以在delay规定的时间200毫秒,在200毫秒的过程中,如果触发了事件,那么就一直移除定时器,然后再添加一个新的定时器,由于定时器规定的时间一直不到达,那么fn就一直不会被执行。直到不再触发事件为止。
跟节流的思路类似。区别在于:节流的思路是,发现定时器那就不执行fn,直到定时器时间到了执行完fn,只会在再次触发的时候再添加新的定时器。而防抖的思路是:在200ms过程中,触发事件 -> 发现有定时器 -> 去除定时器,再添加一个新的定时器。除非在delay时间过程中,没有触发事件 -> 无法发现有定时器 -> 无法去除定时器 -> 成功执行fn。
function debounce(fn, delay = 200){
let timer = null
return function(){
if(timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
let inputName = document.querySelector('#username')
inputName.addEventListener('keyup', debounce(function(){
console.log(this.value)
}))