JS函数的节流和防抖
Posted JettWoo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS函数的节流和防抖相关的知识,希望对你有一定的参考价值。
防抖(debounce): 触发事件后在n秒内函数只能执行一次,如果在n秒内又触发了事件,则会重新计算函数执行事件
非立即执行版本:触发事件后函数不会立即执行,而是在n秒后执行,如果在n秒内触发了事件则会重新计算函数执行时间。
/* 函数防抖 */ var inputDom = document.querySelectorAll("#debounce")[0]; /* 非立即执行防抖 */ var timer = null; inputDom.addEventListener("input", function(){ clearTimeout(timer); var self = this; var arg = arguments; clearTimeout(timer); timer = setTimeout(function(){ //此处不能使用call,应该使用apply,直接将参数放在数组中传 handle.apply(this, arg); }, 800) }); function handle(ev){ var ev = ev || window.event; console.log("ev:", ev); }
/* 封装 */ function debounce(func, wait){ let timer = null; return (function(){ let self = this; let args = arguments; if(timer) clearTimeout(timer); timer = setTimeout(() => { func.apply(self, args) }, wait); }) }
立即执行版本: 触发事件后函数会立即执行,然后n秒内不触发事件才能继续执行函数的效果。
/* 立即执行防抖 */ var inputDom = document.querySelectorAll("#debounce")[0]; var timer; inputDom.addEventListener("input", function(){ if(timer) clearTimeout(timer); // 判断是否在等待时间内 var callNow = !timer; timer = setTimeout(() => { // 等待一段时间后重置timer timer = null }, 1000); // 如果不在等待时间内,则调用事件处理函数 if(callNow) handle.apply(this, arguments); }); function handle(ev){ var ev = ev || window.event; console.log("ev:", ev); }
/* 封装版本 */ function debounce(handle, wait){ let timer; return (function(){ let self = this, args = arguments; if(timer) clearTimeout(timer); let callNow = !timer; timer = setTimeout(() => { timer = null; }, 1000); if(callNow){ handle.apply(self, args); } }); }
双剑合璧版本:
/** * @desc 函数防抖 * @param func 函数 * @param wait 延迟执行毫秒数 * @param immediate true 表立即执行,false 表非立即执行 */ function debounce(func,wait,immediate) { let timeout; return function () { let context = this; let args = arguments; if (timeout) clearTimeout(timeout); if (immediate) { var callNow = !timeout; timeout = setTimeout(() => { timeout = null; }, wait) if (callNow) func.apply(context, args) } else { timeout = setTimeout(function(){ func.apply(context, args) }, wait); } } }
节流(throttle):指连续触发事件但是在n秒中只执行一次函数。节流会稀释函数的执行频率。
时间戳版本:
/* 节流 */ /* 时间戳版本 */ var inputDom = document.querySelectorAll("#debounce")[0]; var previous = 0; inputDom.addEventListener("input", function(){ var now = Date.now(); if(now - previous > 1000){ handle.apply(this, arguments); // 重置时间戳 previous = now; } }); function handle(ev){ var ev = ev || window.event; console.log("ev:", ev); }
/* 封装版本 */ function throttle(handle, wait){ let previous = 0; return (function(){ let now = new Date(); let context = this; let args = arguments; if(now - previous){ handle.apply(context, args); previous = now; } }) }
定时器版本:
/* 封装版本 */ function throttle(handle, wait){ let timeout; return (function(){ let context = this; let args = arguments; if(!timeout){ timeout = setTimeout(() => { timer = null; handle.apply(context, args); }, wait) } }); }
时间戳版和定时器版的节流函数的区别是:时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候。
双剑合璧版本:
/** * @desc 函数节流 * @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; let args = arguments; if(type===1){ let now = Date.now(); if (now - previous > wait) { func.apply(context, args); previous = now; } }else if(type===2){ if (!timeout) { timeout = setTimeout(() => { timeout = null; func.apply(context, args) }, wait) } } } }
参考文献:https://www.jianshu.com/p/c8b86b09daf0
以上是关于JS函数的节流和防抖的主要内容,如果未能解决你的问题,请参考以下文章