javascript中的防抖与节流
一、什么是防抖与节流
防抖与节流本质上是优化高频率执行代码的一种手段。
浏览器中的一些事件(resize,scroll,keypress,mousemove)等在触发时,会不断地调用绑定在事件上的回调函数,极大的浪费资源,降低前端性能。为了优化体验,需要对这类事件进行调用次数的限制,对此我们可以采用 防抖(debounce) 和 节流(throttle) 的方式来减少调用频率。
二、定义
- 防抖:n秒后再执行该事件,如果在n秒内被重复触发,则重新计时。(回城,被打断重新吟唱)
- 节流:n秒内只执行一次,如果在n秒内被重复触发,则只有一次生效。(技能cd,cd时间内触发不管用)
三、代码实现
1、防抖
//简单实现版本
function debounce(func, wait) {
let timeout;
return function () {
let context = this; // 保存this指向
let args = arguments; // 拿到event对象
clearTimeout(timeout)
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
//第三个参数用于判断立即执行的版本
function debounce(func, wait, immediate) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout); // timeout,不为null
if (immediate) {
let callNow = !timeout; // 第一次会立即执行,以后只有时间执行后才会再次触发
timeout = setTimeout(function () {
timeout = null;
}, wait)
if (callNow) {
func.apply(context, args)
}
}
else {
timeout = setTimeout(function () {
func.apply(context, args)
}, wait);
}
}
}
2、节流
//事件戳写法,事件会立即执行,但是停止触发后没有办法再次执行
function throttled1(fn, delay = 500) {
let oldtime = Date.now()
return function (...args) {
let newtime = Date.now()
if (newtime - oldtime >= delay) {
fn.apply(null, args)
oldtime = Date.now()
}
}
}
//定时器写法,delay毫秒后第一次执行,第二次事件停止触发后依然会再一次执行。
function throttled2(fn, delay = 500) {
let timer = null
return function (...args) {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, args)
timer = null
}, delay);
}
}
}
//时间戳和定时器结合的写法
function throttled(fn, delay) {
let timer = null
let starttime = Date.now()
return function () {
let curTime = Date.now() // 当前时间
let remaining = delay - (curTime - starttime) // 从上一次到现在,还剩下多少时间
let context = this
let args = arguments
clearTimeout(timer)
if (remaining <= 0) {
fn.apply(context, args)
starttime = Date.now()
} else {
timer = setTimeout(fn, remaining);
}
}
}
四、区别
相同点:
- 都可以通过使用setTimeout来实现
- 目的都是,降低回调执行频率,节省计算资源
不同点:
- 函数防抖,在一段连续的操作后,处理回调,利用clearTimeout和setTimeout实现;函数节流,每一段时间内只执行一次,频率较高的事件中用来提高性能。
- 函数防抖只在一段时间内的连续触发的最后执行,函数节流一段时间内只执行一次。
五、使用场景
防抖:
- 输入框,在用户输入完成后发送请求。
- 验证码
- 窗口risize,在窗口调整完成后计算窗口大小,放置重复渲染。
节流:
- 滚动加载,加载更多或者滚到底部监听。
- 搜索框,搜索联想功能。