1、事件频繁触发可能造成的问题?
(1)、一些浏览器事件: window.onresize、window.onmousemove等,触发的频率非常高,会造成浏览器性能问题。
(2)、如果向后台发送请求,频繁触发,对服务器造成不必要的压力;例如百度搜索时输入字符,每改变一下输入框字符时就去请求一下,如果不处理就会产生不必要的多余请求,给服务器产生压力。
2、如何限制事件处理函数的频繁调用
主要在于函数调用和函数执行之间的处理
(1)、函数节流
(2)、函数防抖

3、函数节流(throttle)
(1)、理解:
一个函数频繁触发调用,在一定时间T周期内只执行一次调用,实现原理有两种:
(a)、在一定时间T周期的最开始调用,立即执行:在一个函数频繁触发调用时,第一次调用函数立即执行,在往后规定时间T内再次调用该函数不再执行,直到规定时间T后再次调用函数理解执行,周期循环这一过程。
(b)、在一定时间T周期的最开始调用,经过时间T后执行:在一个函数频繁触发调用时,第一次调用函数使用计时器,当计时器经过一定时间T再执行函数,在这一定时间T内其他的函数不予执行。周期循环这一过程。
适合与多次事件按时间平价分配触发。
(2)、应用场景
窗口调整(onresize)
页面滚动(onscroll)
DOM元素拖拽(onmousemove)
抢购疯狂点击(onclick)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>throttle与debounce</title>
</head>
<body>
<div>
<button>(时间戳)节流函数</button>
<button>(计时器)防抖函数</button>
</div>
</body>
<script>
window.onload = function () {
// 以时间戳来实现返回节流函数的工具函数
function timeStampThrottle(callback, delay = 1000) {
let pre = 0; //设置初始调用时间为0
return function (event) {
const current = Date.now(); // 获取当前调用时间
if (current - pre > delay) { // 只用离上次调用callback的时间大于delay时才再次调用callback
callback.call(this, event) // 调用真正处理事件的函数,this作为事件源,参数是event
// 记录此次调用的时间
pre = current
}
}
};
// 以计时器来实现返回节流函数的工具函数
function timeMeterThrottle(callback, delay = 1000) {
let timer = null;
return function (event) {
if (!timer) {
timer = setTimeout(() => {
callback.call(this, event)
timer = null;
}, delay)
}
}
};
function handleClick() {
console.log("执行了函数", this, event);
};
document.getElementsByTagName("button")[0].onclick = timeStampThrottle(handleClick, 2000);
document.getElementsByTagName("button")[1].onclick = timeMeterThrottle(handleClick, 2000);
}
</script>
</html>
4、函数防抖(debounce)
(1)、理解:
在一个函数频繁触发调用时,其中函数A调用后执行的条件是下一次函数B调用与函数A调用时间间隔大于规定时间T,且函数A执行的时间为函数A调用时的时间+规定时间T。
适合多次事件一个响应的情况
(2)、场景:
输入框实时搜索联想(keyup/input)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>debounce函数防抖</title>
</head>
<body>
<div>
<button>函数防抖</button>
</div>
</body>
<script>
window.onload = function () {
function debounce(callback, delay) {
return function (event) {
// 如果上次事件还没有真正执行完成,取消它
if (callback.hasOwnProperty("timeoutId")) {
clearTimeout(callback.timeoutId)
};
// 启动定时器,在delay时间后执行
callback.timeoutId = setTimeout(() => {
// 正在执行事件
callback.call(this, event);
// 删除准备执行的标记
delete callback.timeoutId;
}, delay);
}
};
function handleClick() {
console.log("执行了函数", this, event);
};
document.getElementsByTagName("button")[0].onclick = debounce(handleClick, 2000);
}
</script>
</html>
