函数防抖:当某事件被持续触发时,一定时间内事件没有再触发,事件处理函数才会执行一次,如果设定的时间到来之前,又重新触发了一次事件,就重新开始计时延迟。总结为一句话,多次触发事件,在最后一次延迟规定时间后执行。
简单的函数防抖代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function debounce(fn, wait){ let timeout = null; return function(){ if(timeout !== null) clearTimeout(timeout); timeout = setTimeout(fn, wait); } }
function handle(){ console.log(Math.random()); }
window.addEventListener('scroll', debounce(handle, 1000));
|
我们可以看出,当事件scroll触发后1000ms后,执行handle函数,当滚动事件持续触发时,handle函数是不执行的。
** 案例 **表单输入校验
比如监听输入事件校验邮箱,如果我们每输入一次都要校验邮箱,这就造成了浪费,于是我们可以利用函数防抖,在输入间隔500ms时,进行校验。
1 2 3 4 5 6 7 8 9 10 11 12
| const reg = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
$('#email').on('keyup', verfiyEmail());
function verifyEmail(){ let timer = null; return function(){ if(timer !== null) clearTimeout(timer); timer = setTimeout(function(){ console.log('执行校验') }, 500) } }
|
函数节流
函数节流:当事件持续触发时,保证一定时间段只执行一次的函数。
函数节流主要有两种实现方法:时间戳和定时器的方式。接下来分别实现这两种方式。
函数节流代码(时间戳):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| let throttle = function(fn, delay){ let prev = Date.now(); return function(){ let context = this; let args = arguments; let now = Date.now(); if(now - prev >= delay){ fn.apply(context, args); prev = Date.now(); } }; }; function handle(){ console.log(Math.random()); }
window.addEventListener('scroll', throttle(handle, 1000));
|
函数节流代码(定时器):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| let throttle = function(fn, delay){ let timer = null; return function(){ let context = this; let args = arguments; if(!timer){ timer = setTimeout(function(){ fn.apply(context, args); timer = null; }, delay); } } };
function handle(){ console.log(Math.random()) }
window.addEventListener('scroll', throttle(handle, 1000));
|
我们可以看出,时间戳方式的节流代码利用闭包,内部函数保存了开始执行时的时间戳,当事件持续触发时,利用先前的时间戳和现在时间戳对比,达到设定的范围执行一次操作函数。定时器方式的节流代码也是类似,在规定的时间段内只维护一个定时器。
** 案例 **限时秒杀活动
我们有一个限时秒杀按钮,用户一般都会在活动倒计时的时候不断地点击按钮,按常规操作,点击一次按钮我们就提交一次请求,这时候的高并发操作肯定不是我们想要的,此时利用节流可以解决问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| let btn = ducument.getElementById('show');
function throttle(fn, wait){ let prev = Date.now(); return function(){ let now = Date.now(); if(now - prev >= wait){ fn(); prev = Date.now(); } } }
function handle(){ console.log('执行提交操作') }
btn.onClick = throttle(handle, 1000);
|
区别:函数节流不管时间触发多频繁,都会保证在规定的时间触发一次;而防抖只是在事件触发的最后一次,在延迟规定的时间后执行函数。