本文共 1731 字,大约阅读时间需要 5 分钟。
所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
效果:如果短时间内大量触发同一事件,只会执行一次函数。
实现:既然前面都提到了计时,那实现的关键就在于这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现:
function debounce(fn, delay) {//防抖 // 定义一个定时器timer,用来记录当前执行函数状态(借助闭包) let timer = null; return function() { // 通过 ‘this’ 和 ‘arguments’ 获取函数的作用域和变量 let context = this; let args = arguments; if (timer) //进入该分支,说明当前正在一个计时过程中,并且又触发了相同事件 clearTimeout(timer); // 所以要取消当前的计时,并重新开始计时 timer = setTimeout(function() { fn.apply(context, args); }, delay); }}// 处理函数function handle() { console.log(Math.random()); }// 滚动事件window.addEventListener('scroll', debounce(handle, 1000));
当持续触发scroll函数,handle函数只会在1秒时间内执行一次,在滚动过程中并没有持续执行,有效减少了性能的损耗。
需要注意的是 this 和 参数的传递
let context = this;let args = arguments;
防抖函数的代码使用这两行代码来获取 this 和 参数,是为了让 debounce 函数最终返回的函数 this 指向不变以及依旧能接受到 e 参数。
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
效果:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。
实现:这里借助setTimeout来做一个简单的实现,加上一个状态位timer来表示当前函数是否处于工作状态。
function throttle(func, delay){//节流 let timer = null; return function(){ let context = this; let args = arguments; if(!timer){ //如果定时器存在,就不执行 timer = setTimeout(function(){ func.apply(context, args); timer = null; }, delay); } }}//调用function handle() { console.log(Math.random());}window.addEventListener('scroll', throttle(handle, 1000));
当触发事件的时候,我们设置了一个定时器,在没到1000ms之前这个定时器为null,而到了规定时间执行这个函数并再次把定时器清除。也就是说当第一次触发事件,到达规定时间再执行这个函数,执行之后马上清除定时器,开始新的循环,那么我们看到的效果就是,滚动之后没有马上打印,而是等待1000ms打印,有一个延迟的效果,并且这段时间滚动事件不会执行函数。
防抖是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。
比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。转载地址:http://lnuvi.baihongyu.com/