likes
comments
collection
share

防抖函数中容易出现的问题

作者站长头像
站长
· 阅读数 31

我们生活中在用手机电脑时,有时网速不好,然后你心急,就一直点某个按钮,一直发送请求,如果服务器一直接收你的所有的请求的话,这么多人迟早会爆掉。

这时,防抖函数的作用就体现出来了,他主要是是防止过多相同的请求发送到服务器,他一般会设置一个时间段,你点第一次的时候,开始计时,如果你在这个时间段里发送了第二次请求,那么它就会清除第一次请求,保留第二次请求,又重新计时,以此类推,一直到你没有在这个时间段里发送请求了,自然就不会清除你当前的请求了,所以小伙伴们,以后知道该以什么样的速度点了吧,最好点击时间间隔1秒以上。

防抖函数

没实现防抖功能的函数:

let btn = document.getElementById('btn');
btn.addEventListener('click', () => {
    setTimeout(() => {
        console.log('提交');
    }, 1000)
})

连续快速点击后

防抖函数中容易出现的问题

实现防抖功能的函数:

// 获取按钮元素
let btn = document.getElementById('btn');

// 定义处理点击事件的函数
function handle() {
    console.log('提交');
}

// 为按钮添加点击事件监听器,调用防抖函数包装的处理函数
btn.addEventListener('click', debounce(handle));

// 防抖函数
function debounce(fn) {
    let timer = null; // 定时器变量,用于存储定时器ID

    return function (e) {
        clearTimeout(timer); // 清除之前的定时器,确保只有最后一个定时器生效
        timer = setTimeout(fn, 1000); // 设置新的定时器,延迟执行传入的处理函数 fn
    }
}

连续快速点击后

防抖函数中容易出现的问题

防抖函数中的问题

实现防抖函数不难,但是却存在两个问题,this指向和事件(e)被篡改,有些人可能对这两个问题不太懂,看如下:

1. this指向出错

输出handle中的this:

let btn = document.getElementById('btn');
function handle() {
    //ajax请求
    console.log('提交',this);
}
btn.addEventListener('click', debounce(handle))
function debounce(fn) {
    let timer = null;
    return function () {
        clearTimeout(timer)
        timer = setTimeout(fn, 1000)
    }
}

防抖函数中容易出现的问题 this指向window,这显然不是我们想要的,你想一下,我要handle里this指向window有什么用,又不要用到window里的属性,我现在要用的是btn里的属性,况且,原本this指向的就是btn,只不过由于要实现防抖功能把handle当成了参数传递给了debounce函数,因此handle里this指向发生了转变,为了this指向重回正轨,我们有两种方法:

  • 使用箭头函数和call
let btn = document.getElementById('btn');
function handle() {
    console.log('提交', this);
}

btn.addEventListener('click', debounce(handle))

function debounce(fn) {
    let timer = null;
    return function () {
        clearTimeout(timer)
        timer = setTimeout(() => {
            fn.call(this)
        }, 1000)
    }
}

改变this指向,可以使用显示绑定,强行掰弯this指向。我们分析了下,发现debounce函数里的this指向的是btn,于是我们这样做:箭头函数没有this,所以箭头函数里的this,是外层函数debounce的,用call将fn中this掰到了debounce函数里this,this就回到正轨了。

防抖函数中容易出现的问题

诶~,舒服了。

  • 保存this,和使用call
let btn = document.getElementById('btn');

function handle() {
    console.log('提交', this);
}

btn.addEventListener('click', debounce(handle))

function debounce(fn) {
    let timer = null;
    return function () {
        const that = this
        clearTimeout(timer)
        timer = setTimeout(function () {
            fn.call(that)
        }, 1000)
    }
}

2. 事件(e)改变

handle函数里,输出事件e

let btn = document.getElementById('btn');

function handle(e) {
    console.log('提交', e);
}

btn.addEventListener('click', debounce(handle))

function debounce(fn) {
    let timer = null;
    return function () {
        const that = this
        clearTimeout(timer)
        timer = setTimeout(function () {
            fn.call(that)
        }, 1000)
    }
}

防抖函数中容易出现的问题

handle函数中的事件e又跑哪去了。。。。。

看看debounce函数中的有没事件e(叹气):

let btn = document.getElementById('btn');

function handle(e) {
    console.log('提交', e);
}

btn.addEventListener('click', debounce(handle))

function debounce(fn) {
    let timer = null;
    return function (e) {
        console.log(e,'-----');
        const that = this
        clearTimeout(timer)
        timer = setTimeout(function () {
            fn.call(that)
        }, 1000)
    }
}

防抖函数中容易出现的问题

好家伙,原来是跑这里来了,debounce函数简直就是强盗,作为一名新世纪三好青年,必须得纠正这种行为,直接用call把事件给抢回来(义愤填膺),如下:

let btn = document.getElementById('btn');

function handle(e) {
    console.log('提交', e);
}

btn.addEventListener('click', debounce(handle))

function debounce(fn) {
    let timer = null;
    return function (e) {
        console.log(e,'-----');
        const that = this
        clearTimeout(timer)
        timer = setTimeout(function () {
            fn.call(that, e)
        }, 1000)
    }
}

防抖函数中容易出现的问题

做完这些后,有强迫症的我终于放松了。

结语

有些人可能看这篇文章有点困难,因为看懂这篇需要对this指向和闭包有较深的理解,当然还有事件(e),这些人可以先去弄懂闭包和this,再来反复观看此文,如果不知道看哪篇文章,可以看我之前写的关于闭包和this指向的文章,当然我可能写的也不是很好,甚至出错。我写文章,只是想巩固自己的知识点以及加深对this和闭包的理解,如果对你有帮助的话,那就再好不过了,感谢阅读!祝你天天向上!!!

转载自:https://juejin.cn/post/7367659706866810891
评论
请登录