在进行窗口的resize、scroll,输入框内容校验等操作时,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕。此时我们可以采用debounce(防抖)和throttle(节流)的方式来减少调用频率,同时又不影响实际效果。

防抖(debounce)

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

如下图,持续触发scroll事件时,并不执行handle函数,当1000毫秒内没有触发scroll事件时,才会延时触发scroll事件。

JavaScript事件中的防抖和节流

若不设置防抖函数,在事件持续触发的过程中频繁执行函数,结果如下:

1
2
3
4
5
6
7
8
9
10
<div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;"></div>
<script>
let num = 1;
let content = document.getElementById('content');

function count() {
content.innerHTML = num++;
};
content.onmousemove = count;
</script>

JavaScript事件中的防抖和节流

有两种方式设置防抖函数

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function debounce(func, wait) {
    let timeout;
    return function () {
    let context = this;
    let args = arguments;
    if (timeout) {
    clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
    func.apply(context, args)
    }, wait);
    }};

    可以这样绑定事件:

    1
    content.onmousemove = debounce(count,1000);

    JavaScript事件中的防抖和节流

  • 立即执行:触发事件后函数会立即执行,然后n秒内不触发事件才能继续执行函数的效果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function debounce(func, wait) {
    let timeout;
    return function () {
    let context = this;
    let args = arguments;
    if (timeout) {
    clearTimeout(timeout);
    }
    let callNow = !timeout;
    timeout = setTimeout(() => {
    timeout = null;
    }, wait)
    if (callNow) {
    func.apply(context, args);
    }
    }};

    JavaScript事件中的防抖和节流

节流(throttle)