防抖
函数防抖是优化高频率执行 js 代码的一种手段,可以让被调用的函数在一次连续的高频操作过程中只被调用一次
函数防抖作用:减少代码执行次数, 提升网页性能
比如,在谷歌引擎上输入自己想要搜索的内容时,当输入 j 时,为了更好的用户体验,通常都会出现对应的联想内容,这些联想内容通常都是保存在服务器上的
假设每输入一个字母就会发送一次网络请求,那么输入 javascript 就会发送 10 次网络请求,这会大大损耗系统性能,事实上我们并不需要这么多的网络请求,正确做法是在合适的情况下再发送网络请求
我们可以监听用户在某个时间内是否有再次触发事件,如果没有则发送网络请求
函数防抖应用场景:oninput / onmousemove / onscroll / onresize 等事件
用 input 模拟网络请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<input type="text" class="search" />
<script>
let search = document.getElementsByClassName("search")[0];
let count = 0; // 记录触发的网络请求次数
function oInputChange() {
count++;
console.log(`发送了${count}次网络请求`);
console.log(this);
}
search.oninput = oInputChange;
</script>
</body>
</html>
当连续输入 javas 时共发送了 5 次网络请求
自定义防抖函数
思路:
当触发一个函数时,并不会立即执行这个函数,而是通过定时器来延迟函数的执行
如果在延迟时间内,有重新触发函数,那么取消定时器
如果在延迟时间内,没有重新触发函数,那么这个函数就正常执行(执行传入的函数)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<input type="text" class="search" />
<script>
let search = document.getElementsByClassName("search")[0];
let count = 0; // 记录触发的网络请求次数
function oInputChange() {
count++;
console.log(`发送了${count}次网络请求`);
console.log(this);
}
search.oninput = debounce(oInputChange, 1000);
function debounce(fn, delay) {
let timer = null;
return function () {
let _self = this,
args = arguments;
timer && clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(_self, args);
}, delay);
};
}
</script>
</body>
</html>
再次输入 javas 时只发送了一次网络请求
节流
函数节流也是优化高频率执行 js 代码的一种手段,可以减少高频调用函数的执行次数
函数节流作用:减少代码执行次数, 提升网页性能
函数节流应用场景:比如,监听页面的滚动事件、鼠标移动事件、用户频繁点击按钮操作
函数节流和函数防抖区别:
- 函数节流是减少连续的高频操作函数执行次数 (例如连续调用 10 次, 可能只执行 3-4 次)
- 函数防抖是让连续的高频操作时函数只执行一次(例如连续调用 10 次, 但是只会执行 1 次)
自定义节流函数
function throttle(fn, delay) {
let timer = null;
let flag = true;
return function () {
if (!flag) return;
flag = false;
let _self = this,
args = arguments;
timer && clearTimeout(timer);
timer = setTimeout(function () {
flag = true;
fn.apply(_self, args);
}, delay);
};
}