面试之手写防抖节流

栏目: IT技术 · 发布时间: 3年前

内容简介:关注前端体验或性能优化的应该有听说过在短时间内多次触发同一个函数,只执行最后一次。举例:搭乘公交车的时候,陆续有不同的乘客上车,但师傅只会在最后一个乘客上车后才关门。

面试之手写防抖节流

关注前端体验或性能优化的应该有听说过 防抖节流 。那么,什么是防抖节流呢?

防抖

概念

在短时间内多次触发同一个函数,只执行最后一次。

举例:搭乘公交车的时候,陆续有不同的乘客上车,但师傅只会在最后一个乘客上车后才关门。

效果演示

防抖前

面试之手写防抖节流

防抖后

面试之手写防抖节流

应用场景

  • 表单输入验证

  • 表单输入触发搜索 ajax

  • resize/scroll/touch/mouseove 事件

实现

简单版本

function debounce(fn, wait = 1000) {
  let timer = null;

  return function debounced(...args) {
    // 重置计时器
    if (timer) clearTimeout(timer);

    // 新计时器
    timer = setTimeout(() => {
      fn(...args);
      timer = null;
    }, wait);
  };
}

可以看出 debounce 函数的实现原理就是通过计时器延迟函数执行,短时间内再次触发时重置并添加新计时器。此时的输出函数还有个缺陷,就是 this 指向 global ,我们需要让它指向原本指向的变量。

function debounce(fn, wait = 1000) {
  let timer = null;

  return function debounced(...args) {
    // 重置计时器
    if (timer) clearTimeout(timer);

    // 新计时器
    timer = setTimeout(() => {
      fn.apply(this, ...args);
      timer = null;
    }, wait);
  };
}

现在我们实现了一个简单的防抖函数。有时候我们会要求函数在第一次触发立即执行,我们来为它添加个参数。

function debounce(fn, wait = 1000, immediate = false) {
  let timer = null;

  return function debounced(...args) {
    // 重置计时器
    if (timer) clearTimeout(timer);

    // 首次立即执行
    if (immediate && !timer) {
      fn.apply(this, ...args);

      timer = setTimeout(() => {
        timer = null;
      }, wait);

      return;
    }

    // 新计时器
    timer = setTimeout(() => {
      fn.apply(this, ...args);
      timer = null;
    }, wait);
  };
}

我们还可以为其添加取消的功能。

function debounce(fn, wait = 1000, immediate = false) {
  let timer = null;

  function debounced(...args) {
    // 重置计时器
    if (timer) clearTimeout(timer);

    // 首次立即执行
    if (immediate && !timer) {
      fn.apply(this, ...args);

      timer = setTimeout(() => {
        timer = null;
      }, wait);

      return;
    }

    // 新计时器
    timer = setTimeout(() => {
      fn.apply(this, ...args);
      timer = null;
    }, wait);
  }

  debounced.cancel = () => {
    clearTimeout(timer);
    timer = null;
  };

  return debounced;
}

此时一个功能完备的 debounce 函数就完成了。

节流

概念

多次触发同一个函数,同一段时间内只执行一次。

举例:获取验证码很多都会限制 60s 的时间,在 60s 内再次获取验证码是无效,只能获取一次。下个60s才能再次获取。

效果演示

节流前

面试之手写防抖节流

节流后

面试之手写防抖节流

应用场景

  • 编辑器语法校验

  • resize/scroll/touch/mouseove 事件

  • 表单输入联想

实现

简单版本

function throttle(fn, wait = 1000) {
  let previous = 0;

  const throttled = (...args) => {
    const now = +new Date();

    if (now - previous > wait) {
      fn.apply(this, args);
      previous = now;
    }
  };

  return throttled;
}

可以看出节流的主要原理就是利用时间差(当前和上次执行)来过滤中间过程触发的函数执行。我们现在为其添加参数来控制是否在开始时会立即触发一次,及最后一次触发是否执行。

function throttle(fn, wait, options = { leading: true, trailing: false }) {
  let timer;
  let previous = 0;

  const { leading, trailing } = options;

  const throttled = function (...args) {
    const now = +new Date();

    if (leading === false && !previous) previous = now;
    if (timer) clearTimeout(timer);

    if (now - previous > wait) {
      fn.apply(this, args);
      previous = now;
    } else if (trailing) {
      // 更新timer
      timer = setTimeout(() => {
        fn.apply(this, args);
        previous = 0;
        timer = null;
      }, wait);
    }
  };

  return throttled;
}

我们还可以为其添加取消的功能。

function throttle(fn, wait, options = { leading: true, trailing: false }) {
    let timer;
    let previous = 0;

    const { leading, trailing } = options;

    const throttled = function (...args) {
        const now = +new Date();

        if (leading === false && !previous) previous = now;
        if (timer) clearTimeout(timer);

        if (now - previous > wait) {
            fn.apply(this, args);
            previous = now;
        } else if (trailing) {
            // 更新timer
            timer = setTimeout(() => {
                fn.apply(this, args);
                previous = 0;
                timer = null;
            }, wait);
        }
    }
    throttled.cancel = () => {
        clearTimeout(timer);
        timer = null;
        previous = 0;
    }


    return throttled;
}

此时一个功能完备的throttle函数也完成了。

总结

防抖和节流是两个在工作中很可能会遇到的问题,弄清楚其作用和原理对技能提升和面试都会有帮助。

参考

欢迎到前端学习打卡群一起学习~516913974


以上所述就是小编给大家介绍的《面试之手写防抖节流》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

网络营销实战密码

网络营销实战密码

昝辉Zac / 电子工业出版社 / 2009.1 / 56.00元

本书是作者几年来网络营销实战的总结,与其他网络营销书籍最大不同之处是:只专注于实战,不谈理论。本书分三部分详细介绍了网络营销实用策略和技巧,并分析了大量实战案例。第一部分介绍市场与产品研究,包括用户、市场和竞争对手的调查;产品、目标市场的确定;价格策略;赢利模式等。第二部分讨论以网络营销为导向的网站设计,包括怎样在网站上卖东西、提高转化率,以及网站目标设定等。第三部分研究怎样给网站带来流量,详细讨......一起来看看 《网络营销实战密码》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

随机密码生成器
随机密码生成器

多种字符组合密码