JS手写节流函数

100 阅读1分钟

节流,就是在一个时间段内只触发一次事件,比如:1秒内只发送一次请求

本项目案例:鼠标移动,div中的文本增加相应的数值

节流:非立即执行版(定时器版本)

  • 效果图

  • 代码
<div id="adder">0</div>
<script>
  const div = document.getElementById('adder')
  // 封装函数,这里可以把num作为参数传入
  let divAdd = function (num) {
    div.innerHTML = parseInt(div.innerHTML) + num
  }
  // 非立即执行版本,定时器版本
  const throttle = function (fn, wait, ...arg) {
    let timer = null
    return function () {
      if (!timer) {
        timer = setTimeout(() => {
          fn.apply(this, arg)     // 此处使用箭头函数,this指向调用该节流函数的对象
          timer = null
        }, wait)
      }
    }
  }
  // 鼠标移动每次加10,每隔2秒加一次
  div.onmousemove = throttle(divAdd, 2000, 10)
</script>

节流:立即执行版本(时间戳版本)

  • 效果图

  • 代码
<div id="adder">0</div>
<script>
  const div = document.getElementById('adder')
  // 封装函数,这里可以把num作为参数传入
  let divAdd = function (num) {
    div.innerHTML = parseInt(div.innerHTML) + num
  }
  // 立即执行版本,时间戳版本
  const throttle = function (fn, wait, ...arg) {
    let pre = 0    // 初始值
    return function () {
      let now = Date.now()    // 获取当前事件戳
      if (now - pre > wait) {
        fn.apply(this, arg)   // 这里的this也指向,调用节流函数的对象
        pre = now;
      }
    }
  }
  // 鼠标移动每次加10,每隔2秒加一次
  div.onmousemove = throttle(divAdd,2000,10)
</script>

节流:合并版本

  • 使用参数来控制是否立即执行
<div id="adder">80</div>
<script>
  const div = document.getElementById('adder')
  const add = function(num){
    div.innerHTML=parseInt(div.innerHTML)+num;
  }
  // 合并版本,使用immediate控制是否立即执行
  const throttle = function (fn, wait, immediate, ...arg) {
    let time = 0
    return function () {
      if (immediate) { // 立即执行
        let now = Date.now()
        if (now - time > wait) {
          fn.apply(this, arg)
          time = now;
        }
      } else {
        if (!time) {  // 非立即执行
          time = setTimeout(() => {
            fn.apply(this, arg)
            time = 0
          }, wait)
        }
      }
    }
  }
  // 鼠标移动每次加10,每隔2秒加一次,不立即执行
  div.onmousemove = throttle(divAdd, 2000,false, 10)
</script>