# Debounce

## 定义

bounce即弹起，debounce的中文意思为“防抖“

## 场景

debounce个人理解的使用场景为，某种经常会触发的事件，等待稳定后最后一次性执行。比较典型的有：

* 键盘输入事件捕捉。等待用户最后输入完成
* scroll事件，等待用户最后滚动结束处理
* resize事件，等待用户最后调整结束处理

## 实现

```javascript
/// 返回一个函数，但是只要它一直持续地被调用，就不会被触发；除非它最后一次被调用停止了n毫秒
// 如果`immediate`参数被传递，那么会直接执行
function debounce(func, wait, immediate){
  var timeout = null;
  
  return excuteFunction(){
    var context = this;
    var args = arguments;
    var later = function(){
      timeout = null
      if(!immediate) func.apply(context, args);
    }
    
    var callNow = immediate && !timeout;
    if(callNow) func.apply(context, args);
    
    // clearTimeout非常关键。如果在timeout完成后later调用前，excuteFunction又被调用，那么timeou会被清除，并接下来被重新赋值开始
    clearTimeout(timeout)
    
    timeout = setTimeout(later, wait);
  }
}
```

## ES6 实现

```javascript
function debounceES6(func, wait, immediate) {
  let timeout
  return (...args) => {
    let callNow = immediate && !timeout
    if (callNow) func.apply(this, args);
    
    clearTimeout(timeout);
    
    timeout = setTimeout(() => {
      timeout = null
      if (!immediate) func.apply(this, args)
    }, wait);
  }
}
```

## 深度

GitHub有用户专门提到利用箭头函数对于this的处理，省略到context的写法

```javascript
function debounce (fn, wait) {
  let t
  return function () {
    clearTimeout(t)
    t = setTimeout(() => fn.apply(this, arguments), wait)
  }
}
```

虽然绝大数情况下箭头函数会调用语义上正确的this，不过考虑如下场景，就会有错误

```javascript
const obj = {
  name: 'foo',
  sayMyName() {
    console.log('My name is', this.name)
  }
}

obj.sayMyName() //-> My name is foo
obj.deb = debounce(obj.sayMyName, 1000)
obj.deb() // Should log -> My name is foo
```

在省略context的写法下，只能输出，因为`My name is`obj的this没有绑定进去。

除非使用

```javascript
obj.deb = debounce(obj.sayMyName.bind(obj), 1000)
obj.deb() // now -> My name is foo 
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mm.ricky.moe/javascript/chang-jian-han-shu/debounce.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
