浅析函数防抖与函数节流
常见实用场景,有滚动加载、搜索框输入、窗口大小拖拽 Resize。
函数防抖(debounce)
函数防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
简单的说,当一个动作连续触发,则只执行最后一次。
举个栗子,坐公交,司机需要等最后一个人进入才能关门。每次进入一个人,司机就会多等待几秒再关门。电梯也是。
可以看一下下面的代码:
//函数防抖的主函数
function fn(callback, wait) {
let timer = null; //计时器
return function() {
let args = arguments; //保存参数列表
let that = this; //保存this环境
if (timer) clearTimeout(timer); //清除计时器
timer = setTimeout(function() { //开启计时器
callback.apply(that, args); //调用回调函数
}, wait);
}
}
//调用防抖函数,使用户输入完后2s再请求数据
window.onload = function() {
var search = document.querySelector('#search');
search.addEventListener('keyup', fn(function() {
var script = document.createElement('script');
script.src = "https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web&sugsid=1441,21107,18560,29523,29521,29721,29568,29221,28703&wd=" + this.value + "&req=2&csor=2&pwd=1&cb=callback";
document.body.appendChild(script);
document.body.removeChild(script);
}, 2000));
}
函数防抖的应用场景
连续的事件,只需触发一次回调的场景有:
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求
- 手机号、邮箱验证输入检测
- 窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
函数节流
限制一个函数在一定时间内只能执行一次。
所以函数节流要纪录 当前的时间 - 上次执行的时间 > 一定的时间 才执行一次
举个栗子:乘坐地铁,过闸机时,每个人进入后3秒后门关闭,等待下一个人进入。
示例代码:
//函数节流的主要代码
function fn(callback, wait) {
let previous = 0; //纪录上次的执行时间
return function() {
let now = Date.now(); //获得当前时间
let args = arguments;
if (now - previous > wait) { //当前时间-上次执行时间>等待时间
callback.apply(this, args); // 立即调用回调函数的核心代码
previous = now; // 将当前时间纪录为上一次的执行时间
}
}
}
//控制mousemove执行时间,防止多次调用函数
window.onload = function () {
var box = document.querySelector('.box');
box.addEventListener('mousemove', fn(function (ev) {
console.log(1);
}, 1000));
}
函数节流的应用场景
间隔一段时间执行一次回调的场景有:
- 滚动加载,加载更多或滚到底部监听
- 谷歌搜索框,搜索联想功能
- 高频点击提交,表单重复提交
异同点比较
相同点:
- 都可以通过使用 setTimeout 实现。
- 目的都是,降低回调执行频率。节省计算资源。
不同点:
- 函数防抖,在一段连续操作结束后,处理回调,利用 clearTimeout 和 setTimeout 实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能。
- 函数防抖关注一定时间连续触发,只在最后执行一次,而函数节流侧重于一段时间内只执行一次。
最后,总结一下函数防抖与函数节流的区别。函数防抖,将多次执行的事件合并成一次。函数节流,保持一段时间执行一次。推荐阅读「涂鸦码龙」翻译的这篇 - 实例解析防抖动(Debouncing)和节流阀(Throttling)加深理解。文章丰富的实例,可深刻感受一下两者的区别。