学习函数防抖和节流~

在日常开发过程中,我们肯定经常需要对一些持续触发事件进行绑定,比如resize、scroll、mousemove 等等(我经常遇到的是按钮被不断点击,被测试题 BUG)。但是不希望事件在持续触发的时候频繁去触发函数;

当遇到这样的时候我们该如何解决呢?就有了 防抖和节流;
让我们先来看看在事件持续触发的过程中频繁执行函数是怎样的一种情况。
贴代码

//html代码 自己复制好
 

当onmousemove事件在div上面移动的时候。持续触发事件并且持续调用函数;


image.png

下面直接看解决办法吧;

防抖(debounce)

所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

这这边写2个函数,分别是不立即执行和立即执行。

//不是立即执行版本
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);
    }
}

当学习网上代码时候。我一个疑惑是setTimeout还有返回值吗?之前真的没注意到。于是百度了一波返回一个 ID(数字),可以将这个ID传递给 clearTimeout() 来取消执行。 哈哈 只怪自己太菜了~

//触发地方调用debounce函数,传入执行函数和时间
content.onmousemove = debounce(count,1000);

好了看下效果吧


png

代码实现逻辑就是(大白话):不断触发函数时候。因为setTimeOut函数发生是持续的。我们就不断的清除掉前一次的执行代码.当停下来时候触发当前的函数就可以了

学习到代码实现的细节
let context = this;
let args = arguments;
func.apply(context, args)

在学习过程中。我看到了以上代码,直接调用传进来函数,功能仿佛也是可以实现的;为什么还这样写呢?是为了让 debounce 函数最终返回的函数 this 指向不变以及依旧能接受到 e 参数。 知道就行吧~

在贴一下立即执行的代码;立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果

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)
    }
}

节流(throttle)

所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。 节流会稀释函数的执行频率。
对于节流,一般有两种方式可以实现,分别是时间戳版和定时器版。

//时间戳版本
function throttle(func, wait) {
    var previous = 0;
    return function() {
        let now = Date.now();
        let context = this;
        let args = arguments;
        if (now - previous > wait) {
            func.apply(context, args);
            previous = now;
        }
    }
}

使用方式依旧:

content.onmousemove = throttle(count,1000);
png

代码实现逻辑就是(大白话):不断触发函数时候。记录上一次执行时间戳和当前的时间戳。如果之间时间差小于传入的时间就触发。

可以看下效果;显示是均匀的1秒钟触发一次了;上面写完时间戳的版本在看下定时器版本的吧;

//定时器版
function throttle(func, wait) {
    let timeout;
    return function() {
        let context = this;
        let args = arguments;
        if (!timeout) {
            timeout = setTimeout(() => {
                timeout = null;
                func.apply(context, args)
            }, wait)
        }
    }
}

代码实现逻辑就是(大白话):其实这个和时间戳版差不多。差别在初始化了一个变量控制触发执行函数。这个函数值在setTimeout中进行改变。实现了均匀触发的效果
好了 今天的学习到此了~:
文藏参考:文章出处

你可能感兴趣的:(学习函数防抖和节流~)