函数防抖和函数节流是两个目的一样的方法,主要用于向服务器发送请求时的优化,防止发送请求的频率过高。不同之处在于,函数防抖是每n秒结束调用一次,函数节流是每n秒内调用一次。
函数防抖 Debounce
概念:在函数被触发n秒后再调用,如果n秒内再次触发,则重新计时。限定在一定时间内函数只能执行一次(防止你手抖点多次),而且执行的是在这一定时间内最后一次调用。
函数去抖就是对于一定时间段的连续的函数调用,只让其执行一次。
function success(){
console.log("提交成功")
}
// 1 定义防抖函数
const debounce = (fn, delay) => {
let timer = null
// 4 把setTimeout函数的结果返回给debounce函数
return (...args) =>{ //省略号表明输入不定参数,所有传递进来的参数都被放到一个数组中,赋值给变量args
// 5 清除前上一次delay时间内触发的函数,确保最后一次触发重新计时调用
clearTimeout(timer)
// 3 设置一个定时器
timer = setTimeout(()=>{ // 注意这里要设置一个匿名函数调用fn()不能直接调用
fn.apply(this, args)},delay) // 用apply绑定debounce对象this,arguments用于传参
}
}
// 2 调用防抖函数
const Ondebounce = debounce(success, 2000)
let btn = document.getElementById("btn")
btn.addEventListener("click", Ondebounce)
函数节流 Throttle
概念:在一个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。
函数节流的核心是,让一个函数不要执行得太频繁,减少一些过快的调用来节流。类似于建一个水坝让水流减缓
方法1
function successThrottle(e){
console.log("节流提交成功")
}
// 1 定义节流函数
const throttle = (fn, delay) =>{
// 5 设置开关,初始化为true,定时器外部调用前改为false,内部的函数调用完才改回true,否则直接返回null
let flag = true
// 4 把setTimeout函数的结果返回给throttle函数
return(...args) =>{
if (!flag) {return null} // 5
flag = false // 5
// 3 设置定时器
setTimeout(()=>{
fn.apply(this,args)
flag = true // 5
},delay)
}
}
// 2 调用节流函数
const OnThrottle = throttle(successThrottle, 2000)
let btn2 = document.getElementById("btn2")
btn2.addEventListener("click", OnThrottle)
方法2
// 1 定义节流函数
const throttle = (fn, delay)=>{
let lastTime = 0
let timer
return (...args)=>{
let now = new Date().getTime()
if (now - lastTime >= delay){
fn.apply(this,args)
lastTime = now
}else{
clearTimeout(timer)
timer = setTimeout(()=>{
fn.apply(this,args)
},delay)
}
}
}
// 2 调用节流函数
const OnThrottle = throttle(successThrottle, 2000)
let btn2 = document.getElementById("btn2")
btn2.addEventListener("click", OnThrottle)
应用场景
函数节流:
- 懒加载,监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次
- DOM 元素的拖拽功能实现(mousemove)
- 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
- 计算鼠标移动的距离(mousemove)
- Canvas 模拟画板功能(mousemove)
- 搜索联想(keyup)
函数防抖:
- 每次 resize/scroll 触发统计事件
- 文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证一次就好)
语法笔记:
windows对象的方法setTimeout()和clearTimeout()
setTimeout(function(){ }, time)
setTimeout("<function name()>", time)
用于在指定的毫秒数后调用函数或计算表达式
- function处可以调用全局作用域的函数,或创建匿名函数
- time的单位是毫秒 3000表示3秒
- 第二种直接写已有函数的时候要加双引号,如果传入的不是一个已有函数,而是像防抖函数那里,在调用的时候再设置具体函数,则要用第一种方法,创建匿名函数,在里面调用,否则这个计时器无效
clearTimeout(id_of_settimeout)
取消由 setTimeout() 方法设置的定时操作。
- id_of_settimeout是给setTimeout()定义的变量名称