一文看懂如何简单实现节流函数和防抖函数

yizhihongxing

引言:

在前端开发中,我们常常需要处理一系列与用户交互相关的事件,如滚动、键盘输入、鼠标移动等等。这些事件会频繁触发,造成过多的资源浪费,因此需要使用节流和防抖函数来解决这个问题。本文将详细讲解如何实现节流和防抖函数。

一、什么是节流函数和防抖函数?

节流函数:在一段时间内,只执行一次函数。比如,一个页面上有多个滚动事件,如果每一次滚动都触发事件处理函数,可能会对性能造成影响,因此我们需要一个函数来控制一个时间段内只执行一次事件处理函数,以节约资源,这就是节流函数。

防抖函数:在一段时间内,如果多次触发同一个事件,只有最后一次触发的事件会执行函数。比如,一个搜索框需要根据用户输入的关键字动态显示数据,如果对于每一次输入都要请求一次数据,会影响性能,因此我们需要一个函数来控制一定时间内只有最后一次输入才会请求数据,这就是防抖函数。

二、如何实现节流函数?

实现思路:

使用时间戳,记录上一次执行函数的时间。
设定一个时间间隔,如果当前时间减去上一次执行函数的时间大于等于这个时间间隔,就执行函数,并更新上一次执行函数的时间。
代码示例:

function throttle(fn, delay) {
  let timer = null;
  let start_time = 0;

  return function() {
    let current_time = +new Date();
    let diff = current_time - start_time;

    if (!start_time || diff >= delay) {
      fn.apply(this, arguments);
      start_time = current_time;
    } else if (!timer) {
      timer = setTimeout(() => {
        fn.apply(this, arguments);
        start_time = +new Date();
        timer = null;
      }, delay - diff);
    }
  }
}

代码解析:

使用闭包保存定时器变量 timer 和上一次执行函数的时间 start_time。
计算当前时间和上一次执行函数的时间差 diff,如果 diff 大于等于时间间隔 delay 或者还没有执行过函数,则执行函数,并更新 start_time。
如果 diff 小于时间间隔 delay,说明还没有到时间间隔,此时需要使用定时器 setTimeout 来控制函数的执行,直到等待的时间间隔 delay 到达后,才执行函数并更新 start_time 以及清空定时器 timer。

三、如何实现防抖函数?

实现思路:

使用定时器和闭包,记录上一次触发事件的时间。
设定一个时间间隔,如果当前时间减去上一次触发事件的时间小于这个时间间隔,就清空定时器并重新设定一个新的定时器,等待下一次触发事件。
如果当前时间减去上一次触发事件的时间大于等于时间间隔,则执行函数并重新记录上一次触发事件的时间。
代码示例:

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

  return function() {
    if (timer) {
      clearTimeout(timer);
    }

    timer = setTimeout(() => {
      fn.apply(this, arguments);
      timer = null;
    }, delay);
  }
}

代码解析:

使用闭包保存定时器变量 timer。
如果在时间间隔内再次触发事件,则清空定时器并重新设定一个新的定时器。
如果时间间隔后触发事件,则执行函数,并清空定时器 timer。

四、实战示例

接下来我们用一个实战示例来演示如何使用节流和防抖函数。

实现需求:

当浏览器窗口滚动时,输出对应窗口位置的 top 值和 left 值,并使用节流函数和防抖函数来控制输出频率。

代码示例:

// 节流函数实现
function throttle(fn, delay) {
  let timer = null;
  let start_time = 0;

  return function() {
    let current_time = +new Date();
    let diff = current_time - start_time;

    if (!start_time || diff >= delay) {
      fn.apply(this, arguments);
      start_time = current_time;
    } else if (!timer) {
      timer = setTimeout(() => {
        fn.apply(this, arguments);
        start_time = +new Date();
        timer = null;
      }, delay - diff);
    }
  }
}

// 防抖函数实现
function debounce(fn, delay) {
  let timer = null;

  return function() {
    if (timer) {
      clearTimeout(timer);
    }

    timer = setTimeout(() => {
      fn.apply(this, arguments);
      timer = null;
    }, delay);
  }
}

let output1 = throttle(() => {
  console.log(`window top: ${window.scrollY}`);
  console.log(`window left: ${window.scrollX}`);
}, 200);

let output2 = debounce(() => {
  console.log(`window top: ${window.scrollY}`);
  console.log(`window left: ${window.scrollX}`);
}, 200);

window.addEventListener('scroll', () => {
  output1();
  output2();
});

代码解析:

定义节流函数 throttle 和防抖函数 debounce。
使用节流函数和防抖函数来处理输出函数,控制输出频率。
在滚动事件上添加事件监听器,分别使用上述定义的节流函数和防抖函数来输出窗口的 top 值和 left 值。

总结:

本文详细讲解了如何使用节流函数和防抖函数来控制事件的频次,从而提高页面的性能。同时,本文还给出了相关的代码实现,并进行了详细解释和分析。希望本文能够对你的前端开发工作有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一文看懂如何简单实现节流函数和防抖函数 - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • JS中setTimeout()的用法详解

    JS中setTimeout()的用法详解 简介 setTimeout() 是 JavaScript 提供的一个计时器函数,该函数可以在指定的时间后调用一个函数或执行一段代码。setTimeout() 可以作为一种延迟执行脚本的方式,通常用于实现一些需要进行异步处理的功能,如定时轮播、延时执行等等。 语法 setTimeout() 函数的语法如下: setTi…

    JavaScript 2023年5月27日
    00
  • 新手入门js闭包学习过程解析

    新手入门JS闭包学习过程解析 JS闭包是JS中一个非常重要且常见的概念,但它的概念对于初学者来说可能会比较难理解和掌握。本文将详细讲解新手如何入门JS闭包,并提供相关示例进行说明。 什么是JS闭包 JS闭包(Closure)是指有权访问另一个函数作用域中变量的函数,即在函数内部创建一个可以访问外部变量的作用域。它是指那些能够访问自由变量的函数,即使在这些函数…

    JavaScript 2023年6月10日
    00
  • 详细介绍8款超实用JavaScript框架

    详细介绍8款超实用JavaScript框架 JavaScript 拥有十分丰富的生态系统,框架也是其中不可忽视的一部分。下面是8款超实用的 JavaScript 框架,它们受欢迎的原因在于它们能帮助程序员节省时间和提高效率。 1. jQuery jQuery 是最受欢迎的 JavaScript 框架之一。jQuery 旨在简化 HTML 文档遍历、事件处理、…

    JavaScript 2023年5月18日
    00
  • JavaScript实现缓动动画

    当网页上的元素发生位移、大小或透明度等变化时,经常会需要添加缓动动画效果,用来让这些变化更加平滑和自然。而JavaScript可以通过改变CSS样式属性值来实现缓动动画效果,下面我将详细讲解一下JavaScript实现缓动动画的完整攻略。 步骤一:获取元素及其样式值 首先,需要获取到需要进行缓动动画的元素,以及元素的样式属性值。一般可以使用document.…

    JavaScript 2023年6月10日
    00
  • 禁用JavaScript控制台调试的方法

    禁用JavaScript控制台调试,即尝试防止网站被不良分子攻击,避免他们利用JavaScript控制台进行远程执行恶意代码或者非授权编辑页面。以下是禁用JavaScript控制台调试的完整攻略: 1. 禁用F12快捷键 在浏览器中按下F12键可以打开JavaScript控制台,因此禁用F12快捷键是禁用JavaScript控制台调试的一种简单方法。代码如下…

    JavaScript 2023年6月11日
    00
  • JS实现倒计时(天数、时、分、秒)

    JS实现倒计时是一种常见的前端实现方式,在各类网站和应用中均有广泛应用。下面是JS实现倒计时的完整攻略: 步骤一:准备页面结构 首先需要在HTML页面中准备好倒计时所需的HTML结构,包括倒计时DOM元素的容器,每个倒计时数字占据的DOM元素等。 例如,下面是一个简单的倒计时页面结构示例: <div class="countdown-wrap…

    JavaScript 2023年5月27日
    00
  • 用JavaScript操作WinRar

    使用JavaScript操作WinRAR需要使用WinRAR的命令行工具。WinRAR命令行工具具有压缩、解压缩文件的功能以及一些其他选项。下面是关于如何使用JavaScript调用WinRAR命令行工具的完整攻略。 1. 下载并安装WinRAR 要使用WinRAR命令行工具,需要安装WinRAR。WinRAR的官方网站为https://www.rarlab…

    JavaScript 2023年5月27日
    00
  • JS array数组检测方式解析

    JS array数组检测方式解析 在JS中,检查一个变量是否为数组的方法有几种。接下来就一并介绍。 Array.isArray() Array.isArray() 方法用于判断一个变量是否为数组,返回布尔值。例如: let arr = [1, 2, 3]; console.log(Array.isArray(arr)); // 输出 true instanc…

    JavaScript 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部