函数节流(Throttle)和函数防抖(Debounce)是在业务开发中经常会用到的一种代码优化方式.它们可以节省计算资源,提升应用的性能和可靠性.
Throtter Function 和 Debounce Function 本质上一种高阶函数,在时间轴上控制函数调用频次.
Throttle
在一个单位时间内,函数只会被调用一次.即使这个单位时间函数被触发多次.
单位时间内 Throttle函数只会调用一次,则如果是连续触发Throttle函数,则两个Throttle函数调用时间差是固定的.
代码
1 2 3 4 5 6 7 8 9 10 11
   | const throttle = (func, limit) => {   let inThrottle;    return function () {     if(!inThrottle) {              func.apply(this, arguments)       inThrottle = true       setTimeout(() => inThrottle = false, limit)     }    } }
  | 
 
使用场景
Throttle使用场景主要是大量时间需要按时间分配执行时:
- 鼠标在固定区域移动UI变化
 
- DOM元素拖拽
 
Debounce
函数在被触发N秒后执行,如果在N秒内再被触发,则重新计时⌛️
Debounce函数在设定的时间段内只会被执行一次,如果在这个时间段内被再次触发,则时间重新计算.
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   |  const debounce = (func,wait,immediate) {   let timeout;   return function () {     let context = this, args = arguments;     var later = function () {       timeout = null;       if(!immediate) func.apply(context, args);     }     let callNow = !immediate&&!timeout;     clearTimeout(timeout);      timeout = setTimeout(later, wait);     if(callNow) func.apply(context, args);   } }
 
  | 
 
使用场景
Debounce使用场景是将多个执行合并成一个执行:
- 给按钮加函数防抖防止表单多次提交
 
- scroll 是否滑倒底部判断
 
- input输入框监听用户输入
 
Demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
   | <!DOCTYPE html> <html lang="en"> <head>   <meta charset="UTF-8">   <meta name="viewport" content="width=device-width, initial-scale=1.0">   <meta http-equiv="X-UA-Compatible" content="ie=edge">   <title>Throttle 和 Debounce</title> </head> <body>   <div>     <label for="input1">正常 keyup监听</label>     <input type="text" id="input1">         <span id="span1"></span>   </div>   <div>     <label for="input2">Throttle keyup监听</label>     <input type="text" id="input2">        <span id="span2"></span>   </div>   <div>     <label for="input3">Debounce keyup监听</label>     <input type="text" id="input3">        <span id="span3"></span>     </div> </body> <script>
  const throttle = (func, limit) => {   let inThrottle;   return function () {     if(!inThrottle) {       func.apply(this, arguments)       inThrottle = true;       setTimeout(() => inThrottle = false, limit);     }   } }
 
  const debounce = (func, wait) => {   let timeout;   return function () {     let context = this, args = arguments;     let later = function () {       func.apply(context, args);       timeout = null;     }     clearTimeout(timeout);     timeout = setTimeout(later, wait);   } }
  const input1 = document.getElementById('input1'); const input2 = document.getElementById('input2'); const input3 = document.getElementById('input3');
  const span1 = document.getElementById('span1'); const span2 = document.getElementById('span2'); const span3 = document.getElementById('span3');
  input1.addEventListener('keyup', function (event) {  span1.innerText = `${span1.innerText} ${event.target.value} ;`; })
  let throttleFunc = throttle( (value) => {   span2.innerText = `${span2.innerText} ${value} ;`; }, 1000)
  let debounceFunc = debounce( (value) => {   span3.innerText = `${span3.innerText} ${value} ;`; }, 1000)
  input2.addEventListener('keyup', function (event) {   throttleFunc(event.target.value) })
  input3.addEventListener('keyup', function (event) {   debounceFunc(event.target.value) })
  </script> </html>
   | 
 
👆DEMO运行效果