返回

从「this」探讨「防抖」与「节流」执行环境

前端

this到底是什么?

在JavaScript中,this是一个特殊变量,它代表着当前函数的执行环境。this的值可以是对象、数组、字符串等任何类型的数据,也可以是undefined或null。

防抖和节流函数中的this

在防抖和节流函数中,this的值通常是调用它们的函数或对象。例如,如果我们有一个防抖函数debounce,如下所示:

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

当我们调用debounce函数时,this的值就是调用它的函数或对象。例如,如果我们有一个对象b,如下所示:

const b = {
  name: 'b',
  debounce: debounce(function () {
    console.log(this.name);
  }, 1000)
};

当我们调用b.debounce函数时,this的值就是b对象。这也可以从上面的代码中看出,因为我们使用了this.name来访问b对象的name属性。

this写错地方了?

在使用防抖和节流函数时,经常会出现一个问题:this写错地方了!这是因为防抖和节流函数的内部函数通常是一个匿名函数,而匿名函数内部的this的值是undefined。例如,如果我们把上面的debounce函数修改一下,如下所示:

function debounce(fn, delay) {
  let timer;
  return function () {
    clearTimeout(timer);
    timer = setTimeout(() => {
      fn(); // 这里写错了!
    }, delay);
  };
}

当我们调用debounce函数时,this的值就是调用它的函数或对象。但是,当内部函数执行时,this的值却是undefined。这会导致fn函数无法正常执行,因为fn函数可能依赖于this的值。

解决方案

为了解决这个问题,我们可以使用箭头函数来定义内部函数。箭头函数没有自己的this值,它会继承父函数的this值。因此,如果我们把上面的debounce函数修改一下,如下所示:

function debounce(fn, delay) {
  let timer;
  return function () {
    clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, arguments); // 这里改成了apply
    }, delay);
  };
}

当我们调用debounce函数时,this的值就是调用它的函数或对象。当内部函数执行时,this的值也会是调用debounce函数时