JavaScript:节流&防抖

简介: JavaScript:节流&防抖

节流

什么是节流

在JavaScript中,节流throttle是一种限制函数执行频率的技术。

当一个函数被频繁调用时,节流能够控制函数执行的次数,以避免过多的计算和资源的浪费。

比如说在游戏中,一个技能的释放是有间隔的。当我们释放了一次技能后,只有过一段时间才能再次释放这个技能。这就是一种节流。

节流的实现

接下来我们就写个函数,来实现节流。我会先为大家展示代码,然后进行解析。

实现节流的一种常见方法是使用定时器。基本的节流函数如下所示:

function throttle(func, wait) {
  let timer;
  return function() {
    if (!timer) {
      timer = setTimeout(function() {
        func.apply(this, arguments);
        timer = null;
      }, wait);
    }
  };
}

该函数接受两个参数:待执行的函数func和等待时间wait

待执行的函数就是我们每隔一段时间需要调用的函数,wait则是在触发一次后,在wait时间内无法再次触发这个函数。

我们首先拆解一下这个函数的大题结构:

function throttle(func, wait) {
  let timer;
  return function() {if (!timer) {...}};
}

其基本结构为:在外层函数throttle设置一个timer变量,然后在内层函数使用了timer变量,并把内层函数作为外层函数的返回值。

这个结构,就是一个标准的闭包结构!(不知道闭包的可以看这篇文章[JavaScript:作用域&变量回收])

那么这个闭包结构有什么用呢?

其保证了 timer这个变量永远不会被销毁,我们在下一次访问这个函数的时候依然可以用上一次留下来的timer,以确定距离上一次的事件也没有到达指定时间。

再看到内层函数:

function() {
    if (!timer) {
      timer = setTimeout(function() {
        func.apply(this, arguments);
        timer = null;
      }, wait);
    }
  };

timersetTimeout的返回值,当timer为空时,就会执行if语句内部的代码:timer = setTimeout(),此时timer就立刻得到了setTimeout的返回值。

然后setTimeout内部的代码要等待 wait时间后才执行。等到 wait时间后,调用函数func,即我们想要节流的函数。随后将 timer = null;保证下一次使用这个函数可以被执行。

在这个过程中,在setTimeout被调用的瞬间,timer就立刻得到了setTimeout的返回值而不为空。这个时间内, if (!timer)就会判断为false,从而不执行内部代码。当 wait时间后,执行 timer = null;,此时if (!timer)就会判断为true,从而进入下一次节流。


另一种常见的实现节流的方式是使用时间戳。基本的节流函数如下所示:

function throttle(func, wait) {
  let previous = 0;
  return function() {
    let now = Date.now();
    if (now - previous > wait) {
      func.apply(this, arguments);
      previous = now;
    }
  };
}

该函数使用一个变量previous来记录上一次函数执行的时间戳。当函数被调用时,首先获取当前的时间戳,然后与上一次执行的时间戳进行比较。如果两个时间戳之间的间隔大于等待时间,则执行函数,并更新上一次执行的时间戳。否则,不执行函数。

此处也是使用了和刚才一样的闭包结构,唯一的区别就是前面使用setTimeout来控制时间,而此处利用时间戳的减法控制时间。

这两种实现节流的方式都可以达到限制函数执行频率的效果,具体选择哪种方式取决于具体的使用场景和需求。但是两者利用的重要思想都是闭包结构保留变量


防抖

什么是防抖

防抖事件指的是在连续触发某个事件时,只有等到一定的时间间隔内没有再次触发,才会执行该事件。其主要目的是防止事件的频繁触发,从而减少不必要的资源消耗和提升性能。

就好比如moba游戏中的回城效果。如果你点击回城后,再次点击回城,那么先前的回城就会被阻断,重新计时。这就是节流的思想。


防抖的实现

防抖的实现通常是通过定时器实现的。当事件触发时,先清除之前的定时器,再重新设置一个新的定时器,在指定的时间间隔内如果没有再次触发事件,则执行该事件。如果在时间间隔内再次触发了事件,则重新设置定时器,并重置计时。

下面是一个示例,使用JavaScript实现一个简单的防抖事件:

function debounce(func, delay) {
  let timer;
  return function() {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, arguments);
    }, delay);
  };
}

上述示例中,使用了debounce函数来实现防抖功能。debounce函数接受一个需要执行的事件处理函数和延迟时间作为参数,返回一个新的函数。当事件触发时,该新函数会清除之前的定时器clearTimeout(timer);,并重新设置一个新的定时器 timer = setTimeout。如果在延迟时间内再次触发了事件,会重置定时器。直到延迟时间内没有再次触发事件时,才会执行事件处理函数。

具体使用:

function handleScroll() {
  console.log('Scroll被触发了');
}
window.addEventListener('scroll', debounce(handleScroll, 200));

在上述示例中,我们在window对象上监听了scroll事件,并使用防抖函数将事件处理函数包裹起来。延迟时间设置为200毫秒,意味着只有在200毫秒内没有再次触发scroll事件时,才会执行handleScroll函数。

同样的,防抖也利用了闭包思想

通过使用防抖事件,可以有效地减少事件的触发次数,提升性能和用户体验。

相关文章
|
6月前
|
前端开发 JavaScript Java
【JavaScript】JavaScript 防抖与节流:以游戏智慧解锁实战奥秘
【JavaScript】JavaScript 防抖与节流:以游戏智慧解锁实战奥秘
73 3
|
3月前
|
前端开发 JavaScript UED
JavaScript防抖和节流的使用及区别
JavaScript防抖和节流的使用及区别
112 57
|
6月前
|
JavaScript 前端开发 UED
深入理解JavaScript中的节流与防抖技术
理解并合理运用节流与防抖技术,可以帮助我们优化事件处理函数的执行频率,从而提升应用的性能和用户体验。这两种技术通过减少不必要的计算和DOM操作,使得Web应用程序能够更加流畅地运行。 通过掌握防抖和节流的实现原理及应用场景,开发者可以更加灵活地编写高效且性能优化的代码,对于面对高频事件处理时尤其重要。在开发中合理选择使用防抖或节流,将直接影响到应用的响应性和效率。
67 1
|
2月前
|
前端开发 JavaScript UED
JavaScript 中的函数防抖与节流详解及实用场景
在前端开发中,处理用户频繁触发的事件,如输入框的输入、按钮点击、窗口调整大小等,常常需要优化性能以减少无效操作。为此,函数防抖(debounce)和函数节流(throttle)是两种常见的性能优化手段。本文将详细介绍两者的区别与实现,并探讨它们的应用场景。
52 1
|
3月前
|
JavaScript 前端开发
js防抖函数返回值问题解决方案
本文介绍了如何在JavaScript中创建一个带有返回值的防抖函数,通过结合Promise来实现。这种防抖函数可以在事件触发一定时间后再执行函数,并能处理异步操作的返回值。文章提供了防抖函数的实现代码和如何在实际项目中使用该防抖函数的示例。
43 1
|
4月前
|
JavaScript 前端开发 UED
JS 防抖与节流
防抖和节流是优化高频事件处理的技术。针对如`scroll`、`resize`等频繁触发的事件,它们能有效减少不必要的回调执行,节省资源。防抖确保在一段时间内仅执行最后一次操作,适用于输入框自动补全等场景;而节流则按固定间隔执行函数,适合拖拽、滚动事件。通过简单的JavaScript实现,可以显著提升应用性能和用户体验。
42 1
JS 防抖与节流
|
7月前
|
JavaScript 前端开发 UED
js的防抖节流
js的防抖节流
41 1
|
7月前
|
JavaScript 前端开发 UED
js的节流
js的节流
38 0
|
7月前
|
测试技术
js_防抖与节流(闭包的使用)
js_防抖与节流(闭包的使用)
51 0
|
7月前
|
JavaScript
JS中防抖和节流的区别是什么
JS中防抖和节流的区别是什么
53 0