# 防抖和节流

> 防抖和节流是 JavaScript 开发中性能优化的重要方案, 下面通过代码教你掌握他们.

## 防抖

>  当持续触发事件时，一定时间段内没有再触发事件，事件处理函数才会执行一次，如果设定的时间到来之前，又一次触发了事件，就重新开始延时。 

```js
function debounce(fun, delay) {
  let timer = null;
  return function(args) {
    let that = this;
    let _args = args;
    clearTimeout(timer);
    timer = setTimeout(function() {
      fun.call(that, _args);
    }, delay);
  };
}
```

### 立即防抖和非立即防抖

非立即执行防抖是触发事件后函数不会立即执行，而是在 n 秒后执行，如果在 n 秒内又触发了事件，则会重新计算函数执行时间。

![非立即执行](https://static.yancey.app/1655a8fd99421ad2.jpg)

立即执行防抖是触发事件后函数会立即执行，然后 n 秒内不触发事件才能继续执行函数的效果。

![立即执行](https://static.yancey.app/1655a9049d597f7e.jpg)

下面是一个综合版的例子。

```js
function debounce(func, wait, immediate) {
  var timeout;

  return function() {
    var context = this;
    var args = arguments;

    if (timeout) clearTimeout(timeout);
    if (immediate) {
      var callNow = !timeout;
      timeout = setTimeout(function() {
        timeout = null;
      }, wait);
      if (callNow) func.apply(context, args);
    } else {
      timeout = setTimeout(function() {
        func.apply(context, args);
      }, wait);
    }
  };
}
```

### 使用场景

* search 搜索联想，用户在不断输入值时，用防抖来节约请求资源
* window 触发 resize 的时候，不断的调整浏览器窗口大小会不断的触发这个事件，用防抖来让其只触发一次

## 节流

>  当持续触发事件时，保证一定时间段内只调用一次事件处理函数。 

```js
function throttle(fn, delay) {
  let canRun = true;
  return function() {
    if (!canRun) {
      return;
    }
    canRun = false;
    setTimeout(() => {
      fn.call(this, arguments);
      canRun = true;
    }, delay);
  };
}
```

节流分为时间戳版和定时器版，下面是一个综合版。

```js
function throttle(func, delay) {
  var timer = null;
  var startTime = Date.now();
  return function() {
    var curTime = Date.now();
    var remaining = delay - (curTime - startTime);
    var context = this;
    var args = arguments;
    clearTimeout(timer);
    if (remaining <= 0) {
      func.apply(context, args);
      startTime = Date.now();
    } else {
      timer = setTimeout(func, remaining);
    }
  };
}
```

### 使用场景

* 鼠标不断点击触发，mousedown(单位时间内只触发一次)
* 监听滚动事件，比如是否滑到底部自动加载更多，用 throttle 来判断

![防抖和节流](https://static.yancey.app/168848565d65c88b.jpg)

## 参考

[7 分钟理解 JS 的节流、防抖及使用场景](https://juejin.im/post/5b8de829f265da43623c4261)

[JS 的防抖与节流](https://mp.weixin.qq.com/s/Vkshf-nEDwo2ODUJhxgzVA)


---

Source: https://yanceyleo.com/post/91396c4a-d58f-4a6e-907f-5cb640f1ac30
Published: 2019-11-18
Tags: JavaScript