在前端开发的过程中,我们经常会需要绑定一些持续触发的事件,如 resize、scroll、mousemove 等等,但有些时候我们并不希望在事件持续触发的过程中那么频繁地去执行函数
<div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;"></div> <script> let num = 1; let content = document.getElementById('content'); function count() { content.innerHTML = num++; }; content.onmousemove = count; </script>
防抖指触发事件在n秒内函数只执行一次,如果在n秒内又触发了事件,则会重新计算函数执行时间
防抖函数分为非立即执行版和立即执行版。
非立即执行版: 触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
function debounce1(func,wait) { let timeout; return function() { let context = this; console.log(context); let args = arguments; console.log(args) if(timeout) clearTimeout(timeout); timeout = setTimeout(()=>{ func.apply(context,args) },wait) } } content.onmousemove = debounce1(count,1000);
立即执行版: 触发事件会立即执行,n秒内不触发事件
function debounce2(func,wait) { let timeout; return function() { let context = this; let args = arguments; if(timeout) clearTimeout(timeout); let callNow = !timeout timeout = setTimeout(()=>{ timeout = null },wait) if(callNow) func.apply(context,args) } } content.onmousemove = debounce2(count,1000);
节流: 指连续触发事件但是在n秒中指执行一次函数。
对于节流一般有2种方式分别是时间戳版和定时器版,区别是时间戳版的函数触发是在时间段内执行,定时器的是在函数触发时间段内结束执行
时间戳版:
let previous = 0; return function() { let now = Date.now(); let context = this; let args = arguments; if(now - previous > wait) { func.apply(context,args); previous = now; } } } content.onmousemove = throttle1(count,1000);
定时器版:
function throttle2(func,wait) { let timeout; return function() { let context = this; let args = arguments; if(!timeout) { timeout = setTimeout(()=>{ timeout = null; func.apply(context,args) },wait) } } } content.onmousemove = throttle2(count,1000);