前端面试之函数防抖debounce与函数节流throttle实现及原理

254 阅读2分钟

前言

函数节流: 指定时间间隔内只会执行一次任务; 函数防抖: 任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行;

场景: 比如连续输入文字后发送 AJAX 请求进行验证,此时需要使用函数节流,只执行一次。 如果是判断浏览器窗口resize时,每次resize都调用处理函数,又很浪费浏览器性能。此时应该采用函数防抖,每隔一段时间执行一次

函数节流throttle

规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。通俗来讲,就是在delay毫秒的时间内,函数只会触发一次。两次触发时间的间隔一定大于delay毫秒

使用场景:鼠标连续多次click事件,mousemove 事件,监听滚动事件,比如是否滑到底部自动加载更多等等...

// 节流函数1
function throttle(fn, delay) {
  let canRun = true;
  return function () {
    if (!canRun) return;
    canRun = false;
    let context = this;
    setTimeout(function () {
      fn.apply(context, arguments)
      canRun = true;
    }, delay)
  }
}
// 节流函数2
function throttle2(fn, delay) {
  let lastTime = 0;
  return function () {
    let nowTime = new Date().getTime();
    if(nowTime - lastTime > delay){
      fn.call(this)
      lastTime = nowTime
    }
  }
}

// 应用
document.addEventListener('scroll', throttle(function(){
  console.log("test");
}, 300));

在此场景下,每隔一段时间,固定间隔执行一次。 在这里插入图片描述

函数防抖debounce

需要一个延时器来辅助实现,延迟执行需要执行的代码,如 果方法多次触发,把上次记录的延迟执行代码用 cleartimeout 清除掉, 重新开始,如果计时完毕,没有方法来访问触发,则执行代码

使用场景:以百度输入框例,比如你要查询XXx,想实现输完了XXx之后,再进行搜索请求,这样可以有效减少请求次数,节约请求资源。

document.addEventListener('scroll', debounce(function () {
  console.log("test");
}, 300))

//防抖
function debounce(fn, delay) {
  var timer = null;
  return function () {
    clearTimeout(timer)
    var context = this;
    timer = setTimeout(function () {
      fn.call(context)
    }, delay)
  }
}

在此场景下如果一直滚动页面,定时器会一直被清理,只有当停止后,才会执行。 在这里插入图片描述