函数防抖
// 防抖函数低配版
function denounceOld(fn, delay) {
// 定时器
let timer = null
// 将debounce处理结果当作函数返回
return function () {
// 保留调用时的this上下文
let context = this
// 保留调用时传入的参数
let args = arguments
// 每次事件被触发时,都去清除之前的旧定时器
if (timer) {
clearTimeout(timer)
}
// 设立新定时器
timer = setTimeout(function () {
fn.apply(context, args)
}, delay)
}
}
// 防抖函数高配版
function denounceNew(func, wait, immediate) {
//timeout存储定时器的返回值,result要执行函数的结果
let timeout,result
let debounced = function () {
// 将执行的上下文记录
let context = this
// 使用args保存event事件
let args = arguments
// 每次执行前先把之前的定时器取消
if (timeout) clearTimeout(timeout)
// 是否要立即执行
if (immediate) {
let callNow = !timeout
timeout = setTimeout(function () {
timeout = null
}, wait)
if (callNow) result = func.apply(context, args)
} else {
timeout = setTimeout(function () {
// 将需要执行的函数的环境指定为context上下文,同时将事件传入
func.apply(context, args)
}, wait)
}
return result
}
debounced.cancel = function () {
clearTimeout(timeout)
timeout = null
}
return debounced
}
函数节流
// 节流函数低配版
let throttleOld = function (func, wait) {
// last为上一次回调触发的时间,第一次设置为0
let last = 0
return function () {
// 保留调用时的this上下文
let context = this
// 保留调用时传入的参数
let args = arguments
// 记录本次触发回调的时间
let now = Date.now()
// 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
if (now - last >= wait) {
// 如果时间间隔大于我们设定的时间间隔阈值,则执行回调,同时将now的值赋给last
last = now
func.apply(context, args)
}
}
}
// 节流函数高配版
let throttleNew = function (func, wait, options) {
let timeout //timeout存储定时器
let context //context存储上下文
let args //args存储func的参数
let result //result存储func执行的结果
let previous = 0 //记录上一次执行func的时间,默认0,也就是第一次func一定执行(now-0)大于wait
if (!options) options = {} // 如果不设置options时,设置为默认options
// 定时器函数
let later = function () {
// 记录这次的函数执行时间
previous = options.leading === false ? 0 : Date.now()
timeout = null
result = func.apply(context, args)
if (!timeout) context = args = null
}
let throttled = function () {
let now = Date.now() // 当前时间
// 如果第一次不执行,previous等于当前时间
if (!previous && options.leading === false) previous = now
// 时间间隔-(当前时间-上一次执行时间)
let remaining = wait - (now - previous)
context = this
args = arguments
//如果remaining<0,那么距离上次执行时间超过wait,如果(now-previous)<0,也就是now<previous
if (remaining <= 0 || remaining > wait) {
// 清除定时器
if (timeout) {
clearTimeout(timeout)
timeout = null
}
previous = now // 记录当前时间
result = func.apply(context, args) //执行函数func
if (!timeout) context = args = null
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining)
}
return result
}
throttled.cancel = function () {
clearTimeout(timeout)
previous = 0
timeout = context = args = null
}
return throttled
}