Skip to content
标签
note
JS
字数
611 字
阅读时间
3 分钟

概述

js
document.getElementById('test').addEventListener("click", debounce(() => console.log('test')))

防抖 指触发事件后在规定时间内回调函数只能执行一次,如果在规定时间内触发了该事件,则会重新开始算规定时间。

简单总结就是 延时执行 最后一次触发

节流 则是防抖实现的效果之一,减少请求资源

区别

一个是多次点击,只触发一次 (回城
一个是一个时间段,只触发一次(技能 cd

实现代码

通过定时器将回调函数进行延时.如果在规定时间内继续回调,发现存在之前的定时器,则将该定时器清除,并重新设置定时器.

js
// 第一版
// 缺点:函数的 this 指向了 window,应该指向 container
function debounce1(fn, delay) {
	let timer = null
	return function() {
		clearTimeout(timer);
		timer = setTimeout(fn, delay)
	}
}

// 第二版
// 缺点:函数的事件对象 event 变成了 undefined
function debounce2(fn, delay) {
	let timer = null
	return function() {
		clearTimeout(timer)
		// console.log(this)   // 这里的this还是指向容器的
		timer = setTimeout(() => {
			fn.call(this) // 绑定this
		}, delay)
	}
}

// 第三版(解决 event 事件对象问题)
function debounce3(fn, delay) {
	let timer = null
	return function() {
		clearTimeout(timer)
		timer = setTimeout(() => {
			fn.call(this, arguments) // 传递参数
		}, delay)
	}
}

// 第四版(立刻执行,停止触发 n 秒后,才可以重新触发执行)
function debounce4(fn, delay, immediate) {
	let timer = null
	return function() {
		if (timer) clearTimeout(timer)
		if (immediate) {
			// 如果已经执行过,不再执行
			var callNow = !timer
			timer = setTimeout(() => {
				timer = null
			}, delay)
			if (callNow) {
				fn.apply(this, arguments)
			}
		} else {
			timer = setTimeout(() => {
				fn.apply(this, arguments)
			}, delay)
		}
	}
}

应用场景

两个条件:
1,如果客户连续的操作会导致频繁的事件回调 (可能引起页面卡顿).
2,客户只关心 "最后一次" 操作 (也可以理解为停止连续操作后) 所返回的结果. 例如:

  • search 搜索联想,用户在不断输入值时,用防抖来节约请求资源。
  • 不断的调整浏览器窗口大小会不断的触发 resize 事件,用防抖来让其只触发一次。
  • 按钮点击: 收藏,点赞,心标等

参考

# js 防抖 原理

深入理解JS---图解防抖

贡献者

The avatar of contributor named as jiechen jiechen

页面历史

撰写