防抖

防抖函数原理:把触发非常频繁的事件合并成一次去执行 在指定时间内只执行一次回调函数,如果在指定的时间内又触发了该事件,则回调函数的执行时间会基于此刻重新开始计算

简易手写版:
// func是用户传入需要防抖的函数
// wait是等待时间
const debounce = (func, wait) => {
  let timer = undefined;
  // 这里返回的函数是每次用户实际调用的防抖函数
  // 如果已经设定过定时器了就清空上一次的定时器
  // 开始一个新的定时器,延迟执行用户传入的方法
  return function (...args) {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, args);
    }, wait);
  };
};

适用场景:

  • 文本输入的验证,连续输入文字后发送 AJAX 请求进行验证,验证一次就好
  • 按钮提交场景:防止多次提交按钮,只执行最后提交的一次
  • 服务端验证场景:表单验证需要服务端配合,只执行一段连续的输入事件的最后一次,还有搜索联想词功能类似

节流

节流函数原理:指频繁触发事件时,只会在指定的时间段内执行事件回调,即触发事件间隔大于等于指定的时间才会执行回调函数。总结起来就是:事件按照一段时间的间隔来进行触发

简易手写版:

时间戳实现

const throttle = (func, wait = 50) => {
  let lastTime = 0;
  return function (...args) {
    let now = Date.now();
    // 将当前时间和上一次执行函数时间对比
    // 如果差值大于设置的等待时间就执行函数
    if (now - lastTime > wait) {
      lastTime = now;
      func.apply(this, args);
    }
  };
};

定时器实现

function throttle(func, delay) {
  var timer = 0;
  return function () {
    var context = this;
    var args = arguments;
    if (timer) return; // 当前有任务了,直接返回
    timer = setTimeout(function () {
      func.apply(context, args);
      timer = 0;
    }, delay);
  };
}

适用场景:

  • 拖拽场景:固定时间内只执行一次,防止超高频次触发位置变动。DOM 元素的拖拽功能实现(mousemove
  • 缩放场景:监控浏览器resize
  • 滚动场景:监听滚动scroll事件判断是否到页面底部自动加载更多
  • 动画场景:避免短时间内多次触发动画引起性能问题

总结

  • 函数防抖:

    限制执行次数,多次密集的触发只执行一次
    
    • 将几次操作合并为一次操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。
  • 函数节流:

    限制执行的频率,按照一定的时间间隔有节奏的执行
    
    • 使得一定时间内只触发一次函数。原理是通过判断是否到达一定时间来触发函数。