防抖和节流函数实现

7/20/2022 js

# 1. 防抖

防抖(debounce):在第一次触发事件时,不立即执行函数,而是给出一个延迟。若在延迟时间内,不再触发事件那么执行函数;若在延迟时间内再次触发事件,那么以最后一次触发的时机重新计算延迟时间再执行函数。说白了,就是解决用户手抖的情况(#...#)

function debounce(fn, delay = 500) {
	let timer = null
	return function (...args) {
		timer && clearTimeout(timer)
		timer = setTimeout(() => fn.apply(this, args), delay)
	}
}

// test
let log = debounce((a) => console.log(a))
btn.onClick = log(1)

wait!!! 这里防抖虽然是防抖了,但是给用户的感觉是有 500ms 的延迟,所以我想做个优化,让它第一次就开始执行了,且上次执行完毕后又可以立即执行,即用户手抖开始前立刻执行函数,用户手抖结束后再执行函数,然后继续重复下一轮,总之不能为了面试而面试对吧?

function myDebounce(fn, delay = 500, immediate = 1) {
	// immediate 为立即执行标志,1默认开始立即执行
	let timer = null
	return function (...args) {
		timer && clearTimerout(timer)

		if (immediate) {
			immediate ^= 1 // 众所周知:1^1==0; 0^1==1
			fn.apply(this, args)
			timer = setTimeout(() => (immediate ^= 1), delay)
		} else
			timer = setTimeout(() => {
				fn.apply(this, args)
				immediate ^= 1
			}, delay)
	}
}

# 2. 节流

节流(throttle):如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效

function throttle(fn, hold = 500) {
	let timer = null
	let start = +new Date()
	return function (...args) {
		timer && clearTimeout(timer)
		let end = +new Date()
		if (end - start >= hold) {
			start = end
			fn.apply(this, args)
		} else timer = setTimeout(() => fn.apply(this, args), hold)
	}
}

# 3. 防抖和节流的区别

防抖:函数在等待一个 delay 延迟后再执行

节流:函数在一个 hold 时间段内只执行一次

简单来说:如果在用户一直点击的情况下:防抖一直都不会触发,直到用户停下来后等待 delay 延迟才会触发,节流是每隔 hold 触发一次

# 参考

1. 函数防抖与节流 (opens new window)

2. 浅谈 js 防抖与节流 (opens new window)

    要么重构,
    要么享受!
    红莲华
    x
    loading...