咱们常常会绑定一些继续触发的事件,比方resize、scroll、mousemove等等,如果事件调用无限度,会减轻浏览器累赘,导致用户体验差,咱们能够应用debounce(防抖)和throttle(节流)的形式来缩小频繁的调用,同时也不会影响理论的成果。
防抖的概念
触发事件后n秒后才执行函数,如果在n秒内触发了事件,则会从新计算函数执行工夫
防抖函数能够分为立刻执行,和非立刻执行两个版本
非立刻执行版本
- 非立刻执行版本
function debounce(fn, wait) { let timer = null return function () { const context = this const args = arguments timer && clearTimeout(timer) timer = setTimeout(() => { fn.apply(context, args) }, wait) }}
此函数一开始不会马上执行,而是等到用户操作完结之后期待wait秒后才执行,如果在wait之内用户又触发了事件,则会从新计算
- 立刻执行版本
function debounce(fn, wait) { let timer = null return function () { const args = arguments const now = !timer timer && clearTimeout(timer) timer = setTimeout(() => { timer = null }, wait) if (now) { fn.apply(this, args) } }}
立刻执行就是触发事件后马上先执行一次,直到用户进行执行事件期待wait秒后再执行一次
咱们能够将两种版本合并成一种
/** * @desc 函数防抖 * @param fn 函数 * @param wait 提早执行毫秒数 * @param immediate true 表立刻执行,false 示意非立刻执行 */ function debounce(fn, wait, immediate) { let timer = null return function () { const context = this const args = arguments timer && clearTimeout(timer) if (immediate) { const now = !timer timer = setTimeout(() => { timer = null }, wait) now && fn.apply(context, args) } else { timer = setTimeout(() => { fn.apply(context, args) }, wait) } } }
节流的概念
间断触发事件但在n秒内只执行一次函数
对于节流有工夫戳和定时器两种版本
- 工夫戳版本
function throttle(fn, wait) { var prev = 0 return function () { let now = Date.now() let context = this let args = arguments if (now - prev > wait) { fn.apply(context, args) prev = now } }}
在继续触发事件的过程中,函数会立刻执行,用户在wait秒内不论执行多少次事件,都会期待wait秒后再执行。
- 定时器版本
function throttle(fn, wait) { var timer = null return function () { const context = this const args = arguments if (!timer) { timer = setTimeout(() => { timer = null fn.apply(context, args) }, wait) } }}
在触发事件的过程中,不会立刻执行,并且每wait秒执行一次,在进行触发事件后还会再执行一次。
工夫戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内完结的时候。
将两种形式合并
/** * @desc 函数节流 * @param fn 函数 * @param wait 提早执行毫秒数 * @param type 1 表工夫戳版,2 表定时器版 */ function throttle(fn, wait, type) { if (type === 1) { var prev = 0 } else { var timer = null } return function() { const context = this const args = arguments if (type === 2) { if (!timer) { timer = setTimeout(() => { timer = null fn.apply(context, args) }, wait) } } else if(type === 1) { const now = Date.now() if (now - prev > wait) { fn.apply(context, args) prev = now } } } }
参考链接