1. 节流(throttle)
why
例如当我们需要检测页面滚动来执行回调函数的时候,若我们不进行任何处理,则会造成很大的性能消耗。
how
实现一个方法,让回调函数在一段时间内只执行一次。
<button id="btn" onclick="better_scroll()">按钮</button>
// fn是我们需要包装的事件回调, interval是时间间隔的阈值
function throttle(fn, interval) {
// last为上一次触发回调的时间
let last = 0
// 将throttle处理结果当作函数返回
return function () {
// 保留调用时的this上下文
let context = this
// 保留调用时传入的参数
let args = arguments
// 记录本次触发回调的时间
let now = +new Date()
// 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
if (now - last >= interval) {
// 如果时间间隔大于我们设定的时间间隔阈值,则执行回调
last = now;
fn.apply(context, args);
}
}
}
// 用throttle来包装点击的回调
const better_scroll = throttle(() => console.log('触发了点击事件'), 1000)
效果展示:在一秒之内方法最多只能调用一次

2. 防抖(debounce)
why
这里以用户注册时验证用户名是否被占用为例,如今很多网站为了提高用户体验,不会再输入框失去焦点的时候再去判断用户名是否被占用,而是在输入的时候就在判断这个用户名是否已被注册,这样的做法不好的是当用户输入每一个字符,都会进行请求判断,不仅对服务器的压力增大了,对用户体验也未必比原来的好。而理想的做法应该是这样的,当用户输入第一个字符后的一段时间内如果还有字符输入的话,那就暂时不去请求判断用户名是否被占用。解决这个问题的方法叫做防抖。
how
设置一个一秒的延时器,当用户在一秒内再次输入时,将延时器重置,直到用户一秒内不再输入数据,这时再去请求。
先用按钮演示:
<button id="btn" onclick="better_scroll()">按钮</button>
// fn是我们需要包装的事件回调, delay是每次推迟执行的等待时间
function debounce(fn, delay) {
// 定时器
let timer = null
// 将debounce处理结果当作函数返回
return function () {
// 保留调用时的this上下文
let context = this
// 保留调用时传入的参数
let args = arguments
// 每次事件被触发时,都去清除之前的旧定时器
if (timer) {
console.log("重置定时器")
clearTimeout(timer)
}
// 设立新定时器
timer = setTimeout(function () {
fn.apply(context, args)
}, delay)
}
}
// 用debounce来包装点击的回调
const better_scroll = debounce(() => console.warn('触发了滚动事件'), 1000)

<input type="text" oninput="better_scroll()">
效果展示:
