总之都是为了节省计算资源。
场景:
任务频繁触发的情况下,只有足够的空闲时间,才执行代码一次。
基本思想:通过闭包保存一个标记(timeout)来保存 setTimeout
返回的值,每当客户输入的时候把前一个 setTimeout
clear 掉,而后又创立一个新的 setTimeout
,这样就能保证输入字符后的 interval
间隔内假如还有字符输入的话,就不会执行 fn
函数了。
函数防抖的要点:也是需要一个setTimeout
来辅助实现。推迟执行需要跑的代码。
假如方法屡次触发,则把上次记录的推迟执行代码用clearTimeout
清掉,重新开始。
假如计时完毕,没有方法进来访问触发,则执行代码。
// 函数防抖function debounce(handlerFunc, interval = 300) { let timeout = null; return function () { clearTimeout(timeout); timeout = setTimeout(() => { handlerFunc.apply(this, arguments); }, interval); };}
//绑定监听window.addEventListener('resize', () => { debounce(this.onResize, 40)}, false);
场景:过多的DOM相关操作可能会导致浏览器挂起,有时候甚至会崩溃。比方:onresize、onscroll、mousemove等。
为了避免相似问题,即可以使用定时器对该函数进行节流。
基本思想:某些代码不可以在没有间断的情况下连续重复执行,就是肯定时间内函数只执行一次。
第一次调用函数,创立一个定时器,在指定的时间间隔之后运行代码。当第二次调用函数时,它会清理前一次的定时器并设置另一个。假如前一个定时器尚未执行,就是将其替换为一个新的定时器,目的是只有在执行函数的请求中止了一段时间之后才执行。
函数节流的要点:公告一个变量(resizeTimeout)当标志位,记录当前代码能否在执行。
注意:只需是代码周期性执行的,都应该使用节流,但是并不能控制请求执行的速率。
// 函数节流function throttle(handlerFunc, timeout = 66) { let resizeTimeout; if (!resizeTimeout) { resizeTimeout = setTimeout(() => { resizeTimeout = null; handlerFunc(); // The actualResizeHandler will execute at a rate of 15fps }, timeout); }}
//绑定监听window.addEventListener('resize', () => { throttle(this.onResize, 40)}, false);
函数防抖和函数节流的名字起得易混淆,要找技巧了解记忆,浅显易懂的说:
函数防抖就像快递小哥先将外卖攒着一起,只有超过规定间隔的时候才集中送一次。
函数节流就像王者荣耀中任务技能,放一次大招之后,需要CD冷却时间过了,才可以再放。
??像这样,是不是就好了解这两个概念了