防抖和节流
防抖和节流都是阻止短时间内多次连续出发的函数
防抖
定义:触发事件后在规定时间内回调函数只能执行一次,如果在规定时间内又触发了该事件,则重新开始计算规定时间。
函数防抖如坐公交车,最后一个人上车,司机才会发车,将多次执行变为最后一次才执行。
应用场景
- 搜索框:用户在不断输入值时,用防抖来节约请求资源
- 按钮多次点击只触发一次
手写防抖
每当事件触发,就重置定时器,直到最后一次事件被触发,n秒后再去执行回调函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>前端面试</title>
</head>
<body>
<button id="debounce">点我防抖!</button>
<script>
window.onload = function() {
// 1、获取这个按钮,并绑定事件
var button = document.getElementById("debounce");
button.addEventListener("click", debounce(sayDebounce,1000));
}
// 2、防抖功能函数,接受传参
function debounce(fn,wait) {
// 4、创建一个标记用来存放定时器的返回值
let timer = null;
return function() {
// 5、每次当用户点击/输入的时候,把前一个定时器清除
clearTimeout(timer);
// 6、然后创建一个新的 setTimeout,
// 这样就能保证点击按钮后的 interval 间隔内
// 如果用户还点击了的话,就不会执行 fn 函数
timer = setTimeout(() => {
fn.apply(this, arguments);
}, wait);
};
}
// 3、需要进行防抖的事件处理
function sayDebounce() {
// ... 有些需要防抖的工作,在这里执行
console.log("防抖成功!");
}
</script>
</body>
</html>
效果: 多次点击按钮只执行一次任务
节流
定义:规定时间n秒内,将触发的事件合并为一次执行
函数节流如:你上厕所,不是喝一口水就去上厕所,而是每隔一段时间才去上厕所
应用场景
- 监听窗口滚动时,计算滚动条的位置,按一定事件的频率获取
- input实时搜索
手写节流
定时器版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>前端面试</title>
</head>
<body>
<button id="throttle">点我节流!</button>
<script>
window.onload = function() {
// 1、获取按钮,绑定点击事件
var button = document.getElementById("throttle");
button.addEventListener("click", throttle(sayThrottle,1000));
}
// 2、节流函数体
function throttle(fn,wait) {
// 4、通过闭包保存一个标记
let flag = true;
return function() {
// 5、在函数开头判断标志是否为 true,不为 true 则中断函数
if(!flag) {
return;
}
// 6、将 canRun 设置为 false,防止执行之前再被执行
flag = false;
// 7、定时器
setTimeout( () => {
fn.apply(this, arguments);
// 8、执行完事件(比如调用完接口)之后,重新将这个标志设置为 true
flag = true;
}, wait);
};
}
// 3、需要节流的事件
function sayThrottle() {
console.log("节流成功!");
}
</script>
</body>
</html>
时间戳版本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>节流</title>
</head>
<body>
<button id="throttle">点我节流!</button>
<script>
window.onload = function () {
// 1、获取按钮,绑定点击事件
var myThrottle = document.getElementById("throttle");
myThrottle.addEventListener("click", throttle(sayThrottle, 3000));
}
// 2、节流函数体
function throttle(fn, wait) {
let time = 0
return function () {
let now = Date.now()
let args = arguments
if (now - time > wait) {
fn.apply(this, args)
time = now
}
}
}
// 3、需要节流的事件
function sayThrottle() {
console.log("节流成功!");
}
</script>
</body>
</html>