JavaScript基础 - 手写节流和防抖函数

节流和防抖,都是为了降低请求频率,减少不必要的损耗。
原则:既要实现节流和防抖的功能,还要保证不对事件处理函数本身的执行上下文产生影响。

防抖 (debounce)

短时间大量触发同一事件,只执行一次函数,实现延迟执行。
具体实现:
每次触发一个事件(比如点击按钮),都重新开始计时(重新设置计时器),
直到xx毫秒内没有下一次操作,才执行这个事件的处理程序。

v0:

function debounce(fn) {
    return function() {
        setTimeout(() => {
            fn();
        }, 1000)
    }
}
const ele = document.getElementById("debounce");
ele.addEventListener("click", debounce(fn));
function fn() {
    console.log("clicked");
}

在debounce()函数中返回了一个函数,这个函数用做事件处理程序,它启动一个定时器,
当计时结束时执行传入的函数fn;

这个版本虽然实现了延时执行,但是没有在每次触发后重置定时器,改进如下

function debounce(fn) {
    let id = null; // 第一次执行时的id为null
    return function() {
        clearTimeout(id);
            id = setTimeout(() => {
                fn();
            }, 1000);
        }
}
const ele = document.getElementById("debounce");
ele.addEventListener("click", debounce(fn));
function fn() {
    console.log("clicked");
}

这样做仍然不完善,因为这里的 fn 作为实际上的事件处理函数,它的
this 指向 window(非严格模式),而不是事件侦听器绑定到的对象;
而且如果向防抖处理后的函数传入参数,fn 将无法接收到。

再改进如下:

function debounce(fn) {
    let id = null; 
    return function() {
        clearTimeout(id);
        id = setTimeout(() => { 
        /* 箭头函数没有自己的 this和 arguments */
            handleChange.call(this, arguments);
        }, 400);
    }
}

节流 (throttle)

节流即每隔一个时间间隔,执行一次任务。
按照上面的思路,给出两种写法:
写法1:
这个写法与防抖很相似,区别只在于定时器的处理。

function throttle(fn) {
    let timeout = null;
    return function() {
        if(!timeout) {
            timeout = setTimeout(()=>{
                timeout = null;
                fn.call(this, arguments);
            }, 400);
        }
    }
}

写法2:

function throttle(fn) {
    let prev = 0;
    return function() {
        let now = Date.now();
        if( now - prev > 400 ) {
            fn.call(this, arguments);
            prev = now;
        }
    }
}
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值