目录
节流
解释
节流(throttle)是指让某一个函数的触发次数在一定时间内限定在一定范围内,最常的情况是一定时间内只触发最初的一次。常用在scroll监听,resize监听,drag监听,某个只提交第一下点击事件的按钮上等。
- 需要明确:因为是函数节流,出现的地方是在调用函数作为参数,而节流函数必然需要所返回一个函数作为那个地方的参数。
- 利用一个定时器,按照以下思路进行设计:执行→定时→在定时内又执行,不触发→在定时外执行,触发,重新定时。需要定时器不被回收防止点一下就创建个新的:闭包。
手写实现
全部计时器实现
/**
* 手写函数节流(计时器)
* @param {Function} fn 被节流的函数
* @param {Number} delayTime 节流延迟时间
* @param {Boolean} isImmediate 是否立即触发执行
* @returns 节流后的函数
*/
function throttle(fn, delayTime = 1000, isImmediate = false){
let timer = null;
let flag = true;
return function(){
let content = this;
let args = arguments;
// 不立即执行的情况
if (!isImmediate) {
if (timer) {
return;
}
timer = setTimeout(() => {
fn.apply(content, args);
timer = null;
}, delayTime);
}
// 立即执行
else {
if (flag) {
if (timer) {
return;
}
fn.apply(content, args);
flag = false;
timer = setTimeout(() => {
timer = null;
flag = true;
}, delayTime);
}
}
}
}
Date.now() 时间戳实现
/**
* 手写函数节流(时间戳),会立即执行
* @param {Function} fn 被节流的函数
* @param {Number} delayTime 节流延迟时间
* @returns 节流后的函数
*/
function throttle_2(fn, delayTime = 1000) {
let curTime = null;
return function() {
let content = this;
let args = arguments;
if(!curTime || Date.now() - curTime >= delayTime) {
fn.apply(content, args);
curTime = Date.now();
}
}
}
混合
可以选择不立即执行则使用计时器实现,立即执行用 Date.now() 实现。
防抖
解释
防抖(debounce)和节流的区别就在于节流是规律触发,防抖是只保留最后一次触发,把前面触发的全覆盖掉来实现。
- 需要明确:因为是函数防抖,出现的地方是在调用函数作为参数,而防抖函数必然需要所返回一个函数作为那个地方的参数
- 同节流,需要计时器、闭包。不同的是节流是直接 return ,不执行对应函数,而防抖是通过 clearTimeout(timer) 来直接清掉计时器从而覆盖。
手写实现
/**
* 手写函数防抖
* @param {Function} fn 被防抖的函数
* @param {Number} delayTime 防抖延迟时间
* @param {Boolean} isImmediate 是否立即触发执行
* @returns 防抖后的函数
*/
function debounce(fn, delayTime = 1000, isImmediate = false) {
let timer = null;
let flag = true;
return function() {
const content = this;
const args = arguments;
// 不立即执行的情况
if (!isImmediate) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(content, args);
timer = null;
}, delayTime)
}
// 立即执行
else {
if (flag) {
if (timer) {
clearTimeout(timer);
}
fn.apply(content, args);
flag = false;
timer = setTimeout(() => {
timer = null;
flag = true;
}, delayTime);
}
}
}
}