一、防抖函数代码实现
防抖:适用于高频函数的【延迟执行】,比如搜索框的联想功能
0、测试代码
Document
1、最基本的防抖函数实现【版本一】
function debounce(fn, delay) {
// 1.定义一个定时器, 保存上一次的定时器
let timer = null
// 2.真正执行的函数
const _debounce = function() {
// 取消上一次的定时器
if (timer) clearTimeout(timer)
// 延迟执行
timer = setTimeout(() => {
// 外部传入的真正要执行的函数
fn()
}, delay)
}
return _debounce
}
2、解决 func内部使用this和event都会丢失【版本二】
function debounce(fn, delay) {
// 1.定义一个定时器, 保存上一次的定时器
let timer = null
// 2.真正执行的函数
const _debounce = function(...args) {
// 取消上一次的定时器
if (timer) clearTimeout(timer)
// 延迟执行
timer = setTimeout(() => {
// 外部传入的真正要执行的函数
fn.apply(this, args)
}, delay)
}
return _debounce
}
3、增加需求,防抖函数首次立即执行【版本三】
function debounce(fn, delay, immediate = false) {
// 1.定义一个定时器, 保存上一次的定时器
let timer = null
let isInvoke = false
// 2.真正执行的函数
const _debounce = function(...args) {
// 取消上一次的定时器
if (timer) clearTimeout(timer)
// 判断是否需要立即执行
if (immediate && !isInvoke) {
fn.apply(this, args)
isInvoke = true
} else {
// 延迟执行
timer = setTimeout(() => {
// 外部传入的真正要执行的函数
fn.apply(this, args)
isInvoke = false
}, delay)
}
}
return _debounce
}
4、增加需求,给防抖函数增加一个取消功能【最终版本四】
function debounce(fn, delay, immediate = false) {
// 1.定义一个定时器, 保存上一次的定时器
let timer = null
let isInvoke = false
// 2.真正执行的函数
const _debounce = function(...args) {
// 取消上一次的定时器
if (timer) clearTimeout(timer)
// 判断是否需要立即执行
if (immediate && !isInvoke) {
fn.apply(this, args)
isInvoke = true
} else {
// 延迟执行
timer = setTimeout(() => {
// 外部传入的真正要执行的函数
fn.apply(this, args)
isInvoke = false
timer = null
}, delay)
}
}
// 封装取消功能
_debounce.cancel = function() {
if (timer) clearTimeout(timer)
timer = null
isInvoke = false
}
return _debounce
}
5、增加需求,给防抖函数增加获取返回值功能【特殊版本五】,有哪两种拿返回值的思路?
// 1.定义一个定时器, 保存上一次的定时器
let timer = null
let isInvoke = false
// 2.真正执行的函数
const _debounce = function(...args) {
return new Promise((resolve, reject) => {
// 取消上一次的定时器
if (timer) clearTimeout(timer)
// 判断是否需要立即执行
if (immediate && !isInvoke) {
const result = fn.apply(this, args)
if (resultCallback) resultCallback(result)
resolve(result)
isInvoke = true
} else {
// 延迟执行
timer = setTimeout(() => {
// 外部传入的真正要执行的函数
const result = fn.apply(this, args)
if (resultCallback) resultCallback(result)
resolve(result)
isInvoke = false
timer = null
}, delay)
}
})
}
// 封装取消功能
_debounce.cancel = function() {
if (timer) clearTimeout(timer)
timer = null
isInvoke = false
}
return _debounce
}
二、节流函数代码实现
节流:适用于高频函数的【分时间段执行】,比如飞机大战里面的按键发射子弹功能
0、测试html代码
Document
1、节流函数最简版实现【版本一】
function throttle(func, interval) {
let lastTime = 0;
const throttleFunc = function () {
let currentTime = new Date().getTime();
let remainTime = interval - (currentTime - lastTime);
if (remainTime < 0) {
func();
lastTime = currentTime;
}
};
return throttleFunc;
}
2、节流函数首次执行可配置【版本二,一般用此版本即可】
function throttle(func, interval, options = { leading: true }) {
let { leading } = options;
let lastTime = 0;
const throttleFunc = function (...args) {
if (!leading && lastTime === 0) {
lastTime = new Date().getTime();
}
let currentTime = new Date().getTime();
let remainTime = interval - (currentTime - lastTime);
if (remainTime < 0) {
func.apply(this, args);
lastTime = currentTime;
}
};
return throttleFunc;
}
3、节流函数末次执行可配置【版本三】,取消功能和返回值功能参照防抖函数实现。
function throttle(
func,
interval,
options = { leading: true, trailing: false }
) {
let { leading, trailing } = options;
let lastTime = 0;
let timer = null;
const throttleFunc = function () {
if (!leading && lastTime === 0) {
lastTime = new Date().getTime();
}
let currentTime = new Date().getTime();
let remainTime = interval - (currentTime - lastTime);
if (timer) clearTimeout(timer);
if (remainTime <= 0) {
func();
lastTime = currentTime;
} else if (trailing) {
timer = setTimeout(() => {
func();
lastTime = new Date().getTime();
}, remainTime);
}
};
return throttleFunc;
}