函数防抖

应用场景

连续的事件,只需触发一次

函数防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
  • 搜索框的输入,不是每输入一次就执行一次方法,最后一次输入完毕再执行方法
  • 手机号,邮箱的验证(在用户停止输入后在检查,而不是用户每输入一次就检查一次,浪费性能)
  • 也可用在浏览器窗口大小的改变上,调整完大小后,再计算,防止重复渲染

如下,让input事件在输入框内停止输入一秒后再触发方法:

打印输入框的值的方法

function log() {
console.log(ipt.value);
}

防抖的方法,传入要触发的方法和要在多长时间后触发

function debounce(fn, wait) {
var timer = null;
return function() {
clearTimeout(timer);
timer = setTimeout(fn, wait);
}
}

给input添加事件监听

ipt.addEventListener("input", debounce(log, 1000));

这样用户在input中输入,停止输入一秒后才会触发方法对用户输入的信息进行操作,节省资源

函数节流

每隔一段时间执行一次回调

  • 滚动加载,加载更多或滚动到底部监听
  • 谷歌搜索框,搜索联想功能
  • 高频点击提交,表单重复提交

这里做一个1秒内点击提交按钮只有一次有效,多次点击不会触发事件:

节流的方法

function throttle(fn, wait) {
let timer;
return () => {
if (timer) {
console.log(timer)
return;
} else {
timer = setTimeout(()=>{
fn();
timer = null;
}, wait);
}
}
}

限制函数一段时间内只能执行一次。因此,通过使用定时任务,延时方法执行。在延时的时间内,方法若被触发,则直接退出方法。从而,实现函数一段时间内只执行一次,
但这个方法有个问题就是点击一下按钮,方法在一秒后触发,下面的方法解决这个问题:

function throttle (fn,wait) {
let last = 0;
return ()=>{
let currentTime = +new Date();
if(currentTime-last>wait){
fn();
last = +new Date();
}
}
}

通过比对上一次执行时间与本次执行时间的时间差与间隔时间的大小关系,来判断是否执行函数。若时间差大于间隔时间,则立刻执行一次函数。并更新上一次执行时间。
添加监听,点击时触发在点击开始一秒中内,再次点击不会触发方法

btn.addEventListener('click', throttle(submit, 1000));

在函数防抖中还有再深一层的东西:
函数防抖其实是分为 “立即执行版” 和 “非立即执行版” 的,根据字面意思就可以发现他们的差别,所谓立即执行版就是 触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。 而 “非立即执行版” 指的是 触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。。

function debounce(func,wait,immediate) {
let timer;

return function () {
let context = this;
let args = arguments;

if (timer) clearTimeout(timer);
if (immediate) {
var callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait)
if (callNow) func.apply(context, args)
} else {
timer = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
}

function handle(){
console.log(Math.random());
}

// window.addEventListener("mousemove",debounce(handle,1000,true)); // 调用立即执行版本
window.addEventListener("mousemove",debounce(handle,1000,false)); // 调用非立即执行版本

​​参考地址​​.