返回

防抖和节流之闭包中this,你抓住了吗?

前端

闭包与this

闭包是 JavaScript 中的一个重要概念,是指函数访问其定义所在域之外的变量。JavaScript 中的 this 是指向当前执行函数的对象,对于普通函数,this 指向谁由该函数的调用方式决定,而箭头函数则不受调用方式影响,始终指向创建它的对象。

防抖和节流

防抖和节流是两种常见的技术,用于在事件频繁触发时,优化函数的执行频率。

  • 防抖:在规定时间内,函数只能执行一次。
  • 节流:在规定时间内,函数只能执行固定次数。

闭包在防抖和节流中的应用

在防抖和节流中,通常需要使用闭包来保存定时器。定时器是一个函数,将在指定的时间后执行。闭包可以确保定时器在函数执行后不会被清除。

普通函数中的this指向问题

在防抖和节流闭包中,使用普通函数时,this 的指向会受到调用方式的影响。

  • 当使用事件监听器调用函数时,this 指向触发事件的元素。
  • 当使用 setTimeout 或 setInterval 调用函数时,this 指向 window 对象。

箭头函数中的this指向

使用箭头函数定义闭包时,this 的指向不受调用方式的影响,始终指向创建它的对象。

使用普通函数和箭头函数的比较

使用普通函数和箭头函数定义防抖和节流闭包的优缺点如下:
普通函数:
优点:在某些情况下可以方便地访问 this,例如事件监听器。
缺点:this 的指向受调用方式的影响。
箭头函数:
优点:this 的指向始终指向创建它的对象,不需要担心 this 的指向问题。
缺点:无法使用 普通函数 的 this 。

使用闭包的防抖和节流示例

以下是一个使用闭包的防抖示例:

function debounce(fn, delay) {
  let timer = null;
  return function () {
    clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, arguments);
    }, delay);
  };
}

以下是一个使用闭包的节流示例:

function throttle(fn, delay) {
  let timer = null;
  let lastCall = 0;
  return function () {
    const now = Date.now();
    if (now - lastCall < delay) {
      clearTimeout(timer);
      timer = setTimeout(() => {
        fn.apply(this, arguments);
        lastCall = now;
      }, delay);
    } else {
      fn.apply(this, arguments);
      lastCall = now;
    }
  };
}

结论

闭包对于防抖和节流至关重要,它可以确保定时器在函数执行后不会被清除。在使用闭包定义防抖和节流函数时,要注意 this 的指向问题。在普通函数中,this 的指向受调用方式的影响,而在箭头函数中,this 的指向始终指向创建它的对象。