防抖和节流及多种实现方式

yizhihongxing

当用户在网页中进行操作时,如点击、滚动、输入等,往往会频繁地触发事件。如果每个事件都立即执行相应的函数,可能会导致性能问题和用户体验不佳,因为这些函数可能需要执行复杂的操作,如计算、网络请求等。

为了优化这种情况,我们可以使用防抖和节流来限制函数的调用次数,从而提高性能和用户体验。

 

防抖

防抖是指在一定的时间间隔内,将多次触发的事件合并成一次执行。

防抖的实现思路是:每次事件被触发时,设置一个计时器,在指定的时间间隔内,如果该事件被再次触发,则清除计时器并重新开始计时,直到指定的时间间隔内没有事件触发为止,然后调用函数。

 

防抖可以用于处理一些频繁触发的事件,如窗口大小改变、输入框输入等。以下是一个简单的防抖函数实现:

function debounce(fn, delay) {
  let timer;
  return function() {
    const context = this;
    const args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function() {
      fn.apply(context, args);
    }, delay);
  };
}

 

这个函数接收两个参数: fn 是要防抖的函数, delay 是防抖时间间隔。返回一个新的函数,在防抖时间间隔内,重复调用这个新函数不会立即触发原函数,只有等时间间隔过去之后才会触发。

 

节流

节流是指在一定的时间间隔内,函数只被调用一次。如果在这个时间间隔内触发了多次事件,只有第一次会调用函数,其余的会被忽略。

节流的实现思路是:每次事件被触发时,如果函数没有在指定的时间间隔内被调用过,则调用函数并设置一个计时器,在指定的时间间隔内不再触发事件。如果在指定的时间间隔内再次触发了事件,则不调用函数,直到指定的时间间隔过去,重新开始调用函数。

 

节流可以用于处理一些频繁触发的事件,如页面滚动、鼠标移动等。以下是一个简单的节流函数实现:

function throttle(fn, delay) {
  let timer;
  return function() {
    const context = this;
    const args = arguments;
    if (!timer) {
      timer = setTimeout(function() {
        fn.apply(context, args);
        timer = null;
      }, delay);
    }
  };
}

这个函数接收两个参数: fn 是要节流的函数, delay 是节流时间间隔。返回一个新的函数,在指定的时间间隔内,只能调用一次原函数。

 

 

防抖和节流的实现方式可以有多种,具体实现应该根据实际场景进行调整。下面介绍一些常见的实现方式。

 

立即执行版和非立即执行版

防抖和节流的实现中,可以根据需求选择立即执行版或非立即执行版。

立即执行版是指在每次触发事件时,立即执行一次函数,然后在指定的时间间隔内不再执行。这种方式适合处理一些需要立即响应的事件,如按钮点击等。

 

以下是立即执行版的防抖函数实现:

function debounce(fn, delay, immediate) {
  let timer;
  return function() {
    const context = this;
    const args = arguments;
    if (immediate && !timer) {
      fn.apply(context, args);
    }
    clearTimeout(timer);
    timer = setTimeout(function() {
      if (!immediate) {
        fn.apply(context, args);
      }
      timer = null;
    }, delay);
  };
}

 

这个函数增加了一个参数 immediate ,用来指定是否立即执行函数。如果设置为 true ,则在触发事件时立即执行函数;否则等待指定的时间间隔后再执行。

 

 

非立即执行版是指在事件停止触发指定时间后才执行一次函数。这种方式适合处理一些连续触发的事件,如输入框输入等。

以下是非立即执行版的防抖函数实现:

function debounce(fn, delay, immediate) {
  let timer;
  return function() {
    const context = this;
    const args = arguments;
    if (timer) {
      clearTimeout(timer);
    }
    if (immediate && !timer) {
      fn.apply(context, args);
    }
    timer = setTimeout(function() {
      if (!immediate) {
        fn.apply(context, args);
      }
      timer = null;
    }, delay);
  };
}

这个函数与立即执行版的实现相似,区别在于多了一个 if (timer) { clearTimeout(timer); } 判断。如果计时器已经存在,则在重新设置计时器之前先清除之前的计时器。

 

时间戳版和定时器版

防抖和节流的实现中,可以根据需求选择时间戳版或定时器版。

时间戳版是指在事件触发后,记录下当前的时间戳,并在下次事件触发时再次记录时间戳。在指定的时间间隔内,如果事件再次触发,则更新时间戳。如果时间戳与当前时间的差值超过了指定的时间间隔,则执行函数。这种方式适合处理一些需要立即响应的事件,如按钮点击等。

 

以下是时间戳版的节流函数实现:

function throttle(fn, delay) {
  let last = 0;
  return function() {
    const context = this;
    const args = arguments;
    const now = +new Date();
    if (now - last > delay) {
      fn.apply(context, args);
      last = now;
    }
  };

这个函数中, last 记录上次执行函数的时间戳,每次事件触发时,计算当前时间戳与上次执行函数的时间戳的差值,如果超过指定的时间间隔,则执行函数并更新 last 。

 

 

定时器版是指在事件触发后,设置一个定时器,在指定的时间间隔内不再触发事件。如果在指定的时间间隔内再次触发了事件,则不执行函数,直到定时器到期后再次执行函数。这种方式适合处理一些连续触发的事件,如页面滚动、鼠标移动等。

 

以下是定时器版的节流函数实现:

function throttle(fn, delay) {
  let timer;
  return function() {
    const context = this;
    const args = arguments;
    if (!timer) {
      timer = setTimeout(function() {
        fn.apply(context, args);
        timer = null;
      }, delay);
    }
  };
}

这个函数与之前介绍的非立即执行版的防抖函数实现类似,区别在于将 setTimeout 的时间间隔设置为指定的时间间隔,而不是事件触发后的延迟时间。

防抖和节流的主要区别在于它们限制函数调用的方式不同。防抖是指在指定的时间间隔内将多次触发的事件合并成一次执行,而节流是指在指定的时间间隔内,函数只被调用一次。同时,防抖和节流也有一些缺点,比如可能会导致事件响应延迟或事件被忽略等问题。因此,在实际使用中,需要根据场景进行权衡和选择。

 

原文链接:https://www.cnblogs.com/ronaldo9ph/p/17348583.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:防抖和节流及多种实现方式 - Python技术站

(0)
上一篇 2023年4月22日
下一篇 2023年4月24日

相关文章

  • 浅谈JavaScript 框架分类

    浅谈JavaScript 框架分类 JavaScript框架是用于简化 JavaScript 代码编写的工具。它们可以提供基础架构、模板解析、数据绑定、路由管理等功能。常见的JavaScript 框架有React、Angular、Vue等。本文将分为两个部分对 JavaScript 框架进行分类介绍。 MVC/MVP/MVVM框架 基于MVC/MVP/MVV…

    JavaScript 2023年5月18日
    00
  • 27个JavaScript数组常见方法汇总与实例说明

    「27个JavaScript数组常见方法汇总与实例说明」是一篇介绍JavaScript数组操作方法的文章,主要分为以下三个部分: 一、常见数组方法 这一部分介绍了JavaScript中常用的数组操作方法,包括concat()、push()、pop()、shift()、unshift()、reverse()、sort()、slice()、splice()、in…

    JavaScript 2023年5月18日
    00
  • javascript 流畅动画实现原理

    JavaScript 实现流畅动画的原理是通过不断地更新元素的位置或样式来实现视觉上的连续性,使元素看起来像是在不断地移动或变化。 常见的实现流畅动画的方式是通过 setInterval 或 requestAnimationFrame 不断地调用函数,来更新元素的位置或样式。在函数中,可以通过改变元素的 CSS 属性,来实现实时更新元素的效果。 其中,使用 …

    JavaScript 2023年6月10日
    00
  • 详解JavaScript时间处理之几个月前或几个月后的指定日期

    详解JavaScript时间处理之几个月前或几个月后的指定日期 在 JavaScript 中,我们常常需要对日期进行计算和处理,在实际业务开发中经常会遇到需要计算几个月前或几个月后的日期的需求。本篇文章将详细介绍怎样在 JavaScript 中实现这个功能。 1. 思路分析 为了计算 X 个月前或 X 个月后的日期,我们可以先将指定日期转换为时间戳,然后进行…

    JavaScript 2023年5月27日
    00
  • JavaScript实现的encode64加密算法实例分析

    JavaScript实现的encode64加密算法实例分析 简介 encode64是一种基于64个可打印字符来表示二进制数据的编码方式。相比于普通的ASCII码编码而言,它可以更加节约空间。这种编码方式常用于在网络传输中对一些隐私数据进行加密保护。 实现原理 encode64算法的实现原理如下: 将原始数据(二进制)每6位一组,转换成相应的十进制数。 根据以…

    JavaScript 2023年6月1日
    00
  • JS打开层/关闭层/移动层动画效果的实例代码

    下面我分享一下关于JS打开层/关闭层/移动层动画效果的实例代码的完整攻略。 如何打开层 首先在 HTML 文件中添加一个基本的层结构,如下所示: <div id="layer"> <p>这是一个层</p> <button id="closeBtn">关闭</butt…

    JavaScript 2023年6月10日
    00
  • 从此不再惧怕URI编码 JavaScript及C# URI编码详解

    从此不再惧怕URI编码:JavaScript及C# URI编码详解 URI是什么? URI(Uniform Resource Identifier),中文名为统一资源标识符,是用于标识抽象或物理资源的字符串。 在Web中,我们常用URI表示Web资源的位置和ID。 URI分为三个部分: URI = scheme://host[:port]/path[?que…

    JavaScript 2023年5月20日
    00
  • Backbone.js框架中Model与Collection的使用实例

    首先我们先来简单介绍一下Backbone.js框架。Backbone.js是一个轻量级的JavaScript框架,它提供了MVC(Model-View-Controller)的架构,方便我们在前端开发过程中管理数据状态和逻辑。在Backbone.js框架中,最常用的两个组件是Model和Collection。 Model:Model是指一个数据模型,它相当于…

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