🖥️ 前端经典面试题专栏:前端经典面试题 | 理解节流和防抖
🧑💼 个人简介:一个不甘平庸的平凡人🍬✨ 个人主页:CoderHing的个人主页
🍀 格言: ☀️ 路漫漫其修远兮,吾将上下而求索☀️
👉 你的一键三连是我更新的最大动力❤️
目录
一、回答点
二、深入回答
节流和防抖的理解
防抖应用场景:
节流应用场景:
实现节流和防抖
简易版手撸节流函数
简易版手撸防抖函数
困难版手撸节流函数
困难版手撸防抖函数
防抖:事件被触发n秒后执行回调
节流:在规定一个时间段内,只能触发一次事件的回调函数
function throttle(fn, delay) {let curTime = Date.now();return function() {let ctx = this,args = arguments,nowTime = Date.now();// 如果两次时间间隔超过了指定时间,则执行函数。if (nowTime - curTime >= delay) {curTime = Date.now();return fn.apply(ctx, args);}};
}
function debounce(fn, wait) {let timer = null;return function() {let ctx = this,args = arguments;// 如果此时有定时器的话,取消之前的定时器重新记时if (timer) {clearTimeout(timer);timer = null;}// 设置定时器,让事件间隔指定时间后执行timer = setTimeout(() => {fn.apply(ctx, args);}, wait);};
}
function throttle(fn, interval, options = { leading: true, trailing:false }) {// 记录开始时间const { leading,trailing,resultCallBack } = optionslet endTime = 0let timer = null// 触发,执行函数const _throttle = function(...args) {return new Promise((resolve, reject) => {// 获取当前时间触发的时间const newTime = new Date().getTime()if (!endTime && !leading) endTime = newTime// 使用触发的事件和之前的时间间隔及开始时间,计算出 还剩多长时间需要去触发函数const remainTime = interval - (newTime - endTime)if (remainTime <= 0){if (timer) {clearTimeout(timer)timer = null}// 触发函数const result = fn.apply(this, args)if (resultCallBack) resultCallBack (result)resolve(result)// 保留上次触发时间endTime = newTimereturn}if (trailing && !timer) {timer = setTimeout(() => {timer = nullendTime = !leading ? 0 : new Date().getTime()const result = fn.apply(this, args)if (resultCallBack) resultCallBack(result)resolve(resolve)},remainTime)}})}_throttle.cancel = function() {if(timer) clearTimeout(timer)timer = nullendTime = 0}return _throttle
}
function debounce(fn, delay, immediate = false, resultCallback) {// 1.定义一个定时器, 保存上一次的定时器let timer = nulllet invoke = false// 2.真正执行的函数const _debounce = function(...args) {return new Promise((resolve, reject) => {// 取消上一次的定时器if (timer) clearTimeout(timer)// 判断是否需要立即执行if (immediate && !invoke) {const res = fn.apply(this, args)if (resultCallback) resultCallback(res)resolve(res)invoke = true} else {// 延迟执行timer = setTimeout(() => {// 外部传入的真正要执行的函数const res = fn.apply(this, args)if (resultCallback) resultCallback(res)resolve(res)invoke = falsetimer = null}, delay)}})}// 取消功能_debounce.cancel = function() {console.log(timer)if (timer) clearTimeout(timer)timer = nullinvoke = false}return _debounce
}