节流与防抖
大约 2 分钟约 494 字
节流
一个函数执行一次后,只有大于设定的执行周期后才会执行第二次。 有个需要频繁触发函数,出于优化性能角度,在规定时间内,只让函数触发的第一次生效,后面不生效。
实现
// 时间戳 立即执行
function throttle(func, awit) {
let old = 0
return function () {
const that = this
const args = arguments
let now = newDate().valueOf()
if (now - old > wait) {
func.apply(that, func)
old = now
}
}
}
// 使用定时器 第一次不执行,最后一次调用会执行
function throttle(func, wait) {
let timeout
return function () {
const that = this
const args = arguments
if (!timeout) {
timeout = setTimeout(function () {
func.apply(that, args)
timeout = null
}, wait)
}
}
}
应用场景
- OM 元素的拖拽功能实现(mousemove)
- 搜索联想(keyup)
- 计算鼠标移动的距离(mousemove)
- anvas 模拟画板功能(mousemove)
- 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
- 监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次
防抖
一个需要频繁触发的函数,在规定时间内,只让最后一次生效,前面的不生效。
实现
function debounce(func, wait) {
let timeout
return function () {
const that = this
const args = arguments
clearTimeout(timeout)
timeout = setTimeout(function () {
func.apply(that, args)
}, wait)
}
}
// 立即执行防抖
function debounce(func, wait, immediate) {
let timeout
return function () {
const that = this
const args = arguments
clearTimeout(timeout)
if (immediate) {
const callNow = !timeout
timeout = setTimeout(function () {
timeout = null
}, wait)
if (callNow) {
func.apply(that, args)
}
} else {
timeout = setTimeout(function () {
func.apply(that, args)
}, wait)
}
}
}
// 取消防抖
function debounce(func, wait) {
let timeout
let debounced = function () {
const that = this
const args = arguments
clearTimeout(timeout)
timeout = setTimeout(function () {
func.apply(that, args)
}, wait)
}
debounced.cancel = function () {
clearTimeout(timeout)
timeout = null
}
return debounced
}
应用场景
- 每次 resize/scroll 触发统计事件
- 文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证一次就好)