防抖和节流 (简单易懂版)
序言
"什么是防抖? 什么是节流?"
在学习这两个知识点的时候总是会容易搞混哪个是防抖,哪个是节流。
其分别又代表着什么含义,对于在不同的开发需求中如何合理的运用这两个知识点尤为重要。
一、防抖
防抖,顾名思义就是"防止抖动"。
放在按钮的点击事件中即指: 在指定的时间内,你在不停的点击按钮,按钮所绑定的事件处理函数只会在最后一次执行。
也就是当你点击完按钮后,在指定时间内没有再次触发这个按钮的点击,则当指定的时间到了之后,事件的处理函数也就会执行。
假如有一天中午你刚在工地搬完二十车的砖头,你隐约听到了汽车的鸣笛声。
是它来了,运钞车。它承载着你这一年的辛劳和泪水,今天是发工资的日子。
忙碌了一上午,你的双手已经疲惫不堪,你不缓不慢的放下了手上的二十块砖头。
走向了那堆满钞票的队伍前,等待着领取那属于你的劳动成果。
随着时间的流逝,轮到你了。工头指着那一堆说,那堆是你的。
你用手臂拂去额头的汗水,憨笑道:"诶,好嘞!",然后你拿起桌上的签字笔准备签署。
当你正想签名的时候,你的手臂不知觉的抖动了起来,你知道,这种状态下是没办法签字了。
你的双眼凝视着你的手臂,它还在不停的抖动。你的眼角泛起了一丝轻蔑:"呵!防抖, 不过尔尔!"
然后,嘴中默念道:
// 简易防抖函数 function debounce(fn, delay) { let timer = null; return function() { if (timer) { clearTimeout(timer); timer = setTimeout(fn, delay); } else { timer = setTimeout(fn, delay); } }; } // 以下为示例代码: // 签名 function signature(){ document.write('张三') } // 调用防抖函数 debounce(signature, 3000)()
时间一秒,两秒,三秒...终于!它停止了...
你以迅雷不及掩耳耳之势,潇洒的签上了你的大名----"张三"。
二、节流
节流,顾名思义就是节约流水
放在按钮的点击事件中即指: 在指定的时间内,你还是在不停的点击按钮,按钮所绑定的事件处理函数只会执行一次。
换成技能的冷却时间可能会更好理解些:你点击某个技能之后它会进入冷却,在冷却期间无法再次触发这个技能。
时间回到你签完名字时的前二十分钟。
你放下砖头之后,看了看满是砖土的双手,又看了看不远处的水龙头,叹息道:"怎么又停水了..."
你略作思考,便朝着工地对面的公厕走去。
来到公厕门口,你看到一名约是九岁左右的孩童在洗手池中玩耍。你略微皱眉,快步走上前去。
当你正要斥责孩童的不懂事的时候,那名孩童先于你开口说话了。"你可知,何谓节流?"
你一头雾水的走过来,心中奇怪这孩童怎地在此处玩耍还爱自言自语?
待你走近,方知原来孩童玩耍的水池中并无水迹,便开始怀疑公厕是不是也停水了。
正当你还在疑虑之中时,孩童又说话了。"我知道哪里有水,但阁下须回答我一个问题"
"什么问题?"
"何谓节流?"
"不知,还望赐教",你再次皱起了眉头,稍加思索后答道。
"谓之节流,即节约流水。"
"隔壁这个水池的水龙头是好的,你且洗着手并听我道来"
(你的内心):"Hai..."
"就像这个带感应功能的水龙头一样,手放上去之后水龙头就会释放水流出来,但是当过几秒后水流就会停止"
"这就是节约流水,你把手再放上去,水流亦会再次被释放"
"你在几秒内来回将手放在感应器上,水流并不会随之快速释放/暂停,大体相似于此:"
// 简易节流函数 function throttle(fn, delay) { let valid = null; return () => { if (valid) { return false; } valid = true; setTimeout(() => { fn(); valid = false; }, delay); }; } // 以下为代码示例 // 释放流水 function releaseWater() { return "水" } // 调用节流 throttle(releaseWater, 1500)()
听到这里,你仿佛犹如醍醐灌顶,转瞬便明白了其中门道,顺便还请教了下什么是"防抖"。
总结:
①防抖:指定时间内,多次操作只取最后一次操作
②节流: 指定时间内,多次触发操作只会执行第一次
节流和防抖都有很多种,比如下面的立即执行版节流,但是万变不离其宗,知道核心原理便可以一法通时万法通
// 节流 - 立即执行版 function throttleRightNow(fn, delay) { let valid = null; return () => { if (valid) { return false; } valid = true; fn(); setTimeout(() => { valid = false; }, delay); }; }