防抖和节流
防抖(debounce) 和节流(hrottle)平时只是听说用来防止重复操作的问题,具体也还没使用过,在这里做笔记咯。
防抖(debounce)
防抖是指触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间
效果: 如果短时间内大量触发同一事件,只会执行一次函数。
使用情况:适用于表单输入内容的验证和页面resize事件需要根据最终呈现的页面情况进行dom渲染和表单的多次提交等频繁操作。
思路:使用setTimeout实现计时,只要事件触发,就使用clearTimeout清除上一个计时器,直到规定时间停止触发后,才会执行回调函数。
分析:
1、立即执行: 触发事件后函数会立即执行,如果n秒内不触发事件才能继续执行函数。
2、非立即执行: 触发事件后函数不会立即执行,而是在n秒后执行,如果在n秒内又触发了事件,则会重新计算函数执行时间。
实现:
/** * @dec 函数防抖 * @param func 执行函数 * @param wait 延迟执行函数时间 * @param immediate 是否立即执行,true表立即执行,false表非立即执行 */ function debounce(func, wait, immediate) { let timeout; return function () { let context = this; if(timeout) clearTimeout(timeout); if(immediate) { var callnow = !timeout; timeout = setTimeout(() => { timeout = null; //作为开关变量;且作为闭包引用的变量,手动置为null让其脱离执行环境 }, wait); if(callnow) func.apply(context, arguments); } else { timeout = setTimeout(() => { func.apply(context, arguments); }, wait); } } }
节流(throttle)
节流是指高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率.
效果: 如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效.
思路:使用setTimeout
来做一个简单的实现,加上一个状态位来表示当前函数是否处于工作状态:
分析:
1、定时器:在持续触发事件的过程中,函数不会立即执行,而是n秒执行一次,在停止触发后,函数还会执行一次。
2、时间戳: 在持续触发事件的过程中,函数会立即执行,而是n秒执行一次。
/** * @dec 函数节流 * @param func 执行函数 * @param wait 延迟执行函数时间 * @param type 1表时间戳,2表定时器 */ function throttle(func, wait, type) { if(type === 1) { let previous = 0; } else if(type === 2) { let timeout; } return function () { let context = this; if(type === 1) { let now = Date.now(); if(now - previous > wait) { func.apply(context, arguments); previous = now; } } else if(type === 2) { if(!timeout) { timeout = setTimeout(() => { timeout = null; func.apply(context, arguments) }, wait); } } } }
区别:防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。