网易课程学习——JS进阶(防抖与节流)

105 阅读2分钟

防抖和节流经常被放在一起谈论,不论是在面试过程中还是在业务都要熟悉两者的特点,才能更好的回答面试官与对业务进行优化。

防抖(debounce)

有些操作是高频触发的,但是如果每次都进行监听就会浪费许多资源,例如输入框输入的时候,我们想要在用户完成一段输入后,在进行联想操作,这时就可以使用防抖函数。

在事件被触发n秒后再执行回调,如果在这n秒内再次触发,则重新开始计时。

  • 实现思路 事件触发->开启定时器->如果再次触发,则清除旧定时器,开启新定时器->时间到,执行操作
  • 简单实现
function debounce(callback, delay = 1000) {
    if (typeof delay !== 'number') {
        throw new Error('delay must be a number');
    }
    if (typeof callback !== 'function') {
        throw new Error('callback must be a function');
    }
    let _timer = null;
    return function () {
        clearTimeout(_timer);
        _timer = setTimeout(() => {
            callback.apply(this, arguments); // 绑定上下文
        }, delay);
    }
}

节流(throttle)

可以看出防抖函数如果在持续触发事件的时候,会存在一个问题,那就是事件将一直不触发,这显然不能满足部分场景,比如像发送一个请求,应当是点击发送按钮后,立刻发送,但是在一定时间内,不能再次触发,而这就应该使用节流函数。

在事件被触发后的n秒内,再次执行该操作,将不会再次触发事件。

  • 实现思路 事件触发->执行操作->关闭阀门->阀门关闭时,事件触发将无效->时间到,打开阀门->事件触发可再次执行操作
  • 简单实现
function throttle(callback, delay = 1000) {
    if (typeof delay !== 'number') {
        throw new Error('delay must be a number');
    }
    if (typeof callback !== 'function') {
        throw new Error('callback must be a function');
    }
    let _valid = true; // 阀门
    return function () {
        if (_valid) {
            _valid = false;
            callback.apply(this, arguments);
            setTimeout(() => {
                _valid = true;
            }, delay);
        } else {
            return false;
        }
    }
}

总结

  • 防抖和节流都是为了阻止操作的高频触发,从而导致浪费性能
  • 防抖是为了在一段时间内只会触发一次,节流是间隔一段时间触发一次