js 函数的防抖(debounce)与节流(throttle)

目录

序言:

防抖(debounce)

节流(throttle)

 代码示例

附录:

关于节流/防抖函数中 context(this) 的指向解析:

防抖函数中的 this 指向

节流函数中的 this 指向


序言:

我们在平时开发的时候,会有很多场景会频繁触发事件,比如说搜索框实时发请求,onmousemove, resize, onscroll等等,有些时候,我们并不能或者不想频繁触发事件,咋办呢?这时候就应该用到函数防抖和函数节流了!

防抖(debounce)

防抖(debounce)是指在一定时间内,只执行最后一次触发的事件。它适用于那些在连续触发事件的过程中,只关心最后一次触发的结果的情况。

例如,当用户连续输入搜索关键字时,我们可以使用防抖来减少网络请求的次数。在用户停止输入一段时间后,才发送网络请求进行搜索。

下面是一个简单的 JavaScript 实现防抖函数的例子:

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

这个 debounce 函数接受两个参数:func 是要执行的函数,delay 是延迟的时间。在每次触发事件时,它会清除之前设置的定时器,并重新设置一个新的定时器。如果在延迟时间内再次触发事件,定时器会被清除并重新设置。只有在延迟时间结束后没有再次触发事件,才会执行函数。

节流(throttle)

节流(throttle)是指在一定时间内,固定执行事件的频率。它适用于那些在连续触发事件的过程中,需要保持一定的执行频率的情况。

例如,当用户持续滚动页面时,我们可以使用节流来限制处理滚动事件的频率,以避免过多的计算和渲染。

下面是一个简单的 JavaScript 实现节流函数的例子:

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

这个 throttle 函数接受两个参数:func 是要执行的函数,delay 是延迟的时间。在每次触发事件时,它会检查是否存在定时器,如果不存在则设置一个新的定时器,并在延迟时间结束后执行函数。这样可以保证在延迟时间内只执行一次函数。

总结起来,防抖和节流都是用于优化性能和控制事件触发频率的技术。防抖适用于只关心最后一次触发结果的情况,而节流适用于需要保持一定执行频率的情况。

 代码示例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			body {
				height: 200vh;
				/* 为了触发滚动事件,增加页面高度 */
			}
		</style>
	</head>
	<body>
		<h1>防抖和节流示例</h1>

		<script>
			// 防抖函数
			function debounce(func, delay) {
				let timer; // 定时器变量
				return function() {
					clearTimeout(timer); // 清除之前的定时器
					timer = setTimeout(() => {
						func.apply(this, arguments); // 延迟时间结束后执行函数
					}, delay);
				};
			}

			// 节流函数
			function throttle(func, delay) {
				let timer; // 定时器变量
				return function() {
					if (!timer) {
						timer = setTimeout(() => {
							func.apply(this, arguments); // 延迟时间结束后执行函数
							timer = null; // 清空定时器变量
						}, delay);
					}
				};
			}

			// 示例函数:处理滚动事件
			function handleScroll() {
				console.log("处理滚动事件");
			}

			// 使用防抖函数包装处理滚动事件的函数
			const debouncedHandleScroll = debounce(handleScroll, 200);

			// 使用节流函数包装处理滚动事件的函数
			const throttledHandleScroll = throttle(handleScroll, 200);

			// 监听滚动事件,并调用相应的处理函数
			window.addEventListener("scroll", debouncedHandleScroll);
			// 如果要使用节流函数,可以将上面一行改为下面这行
			// window.addEventListener("scroll", throttledHandleScroll);
		</script>
	</body>
</html>

附录:

关于节流/防抖函数中 context(this) 的指向解析:

在防抖和节流函数中,this 的指向非常重要。下面分别解析一下:

防抖函数中的 this 指向

在防抖函数中,如果不加以处理,this 会指向当前调用防抖函数的对象(例如 window 对象)。因此,我们需要使用 Function.prototype.apply() 或 Function.prototype.call() 方法来明确指定 this 的值。

例如,以下代码中的 handleInput 函数在执行时,this 会指向 input 元素本身:

<input type="text" oninput="debouncedHandleInput.call(this, event)">

这里的 this 表示当前的 input 元素。通过 call() 方法将 this 明确指定为 debouncedHandleInput 函数中的 this。

节流函数中的 this 指向

在节流函数中,this 的指向与防抖函数略有不同。在节流函数中,this 通常应该指向事件的目标元素(例如 button 元素),而不是当前调用节流函数的对象(例如 window 对象)。

例如,以下代码中的 handleClick 函数在执行时,this 会指向 button 元素本身:

<button onclick="throttledHandleClick(event)">点击</button>

这里的 this 表示当前的 button 元素。在 throttledHandleClick 函数中,可以使用 this 来获取目标元素的属性、修改样式等操作。

需要注意的是,在使用箭头函数定义防抖和节流函数时,this 的指向不会改变,仍然指向外层作用域的 this。

综上所述,防抖和节流函数中的 this 指向应该根据实际情况进行明确指定。

猜你喜欢

转载自blog.csdn.net/m0_74293254/article/details/134619789