函数节流,防抖区别与应用

函数节流,防抖区别于应用

函数防抖debounce

抖就是函数在那里抖个不停

Demo

let input = document.getElementById('debounce');

input.addEventListener('keyup', function (e) {
    console.log(e.target.value);
})
复制代码

可以看到对于同样的输入,这里输出了很多次,对于这个例子来讲可能不会有太大问题,但是如果将console.log换成ajax请求的话,就会发出很多没有必要的请求;亦或者换成样式的变化,也会造成额外的ReflowRepaint

Resolve(非立即执行)

那么我们只需要保证同样的输入不会造成多次额外的相同输出即可,也就是说,在用户进行一个操作的时候,如果触发了下一次相同的操作,我们总会取消上一次操作,来保证不管怎样在规定的时间内只有一个操作在进行并且完成

function Log(value) {
    console.log(value);
}

function debounce(func, delay) {
    return function (args) {
        let _this = this;
        let _args = args;
        clearTimeout(func.id);
        func.id = setTimeout(function () {
            func.apply(_this, _args);
        }, delay);
    }
}
    
let input = document.getElementById('debounce');

let debounceLog = debounce(Log, 500);

input.addEventListener('keyup', function (e) {
    debounceLog(e.target.value);
})
复制代码

Wow,看来我们想要的效果达成了,其中的核心函数就是debounce,接收两个参数func(函数)和delay(延时),然后返回一个内部函数,并且将外层参数全部传进去

对于内部函数的实现也很简单,只是将调用这个函数本身的延时器绑定到了这个函数的id属性上,然后每次执行这个函数的时候清除上一次的延时器,重新计时,这样就完成了我们的预期,也就是函数防抖

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

Resolve(立即执行)

function debounce(func, delay) {
    return function (args) {
        let _this = this;
        let _args = args;
        if(func.id) clearTimeout(func.id);
        
        func.id = setTimeout(function () {
            func.id = null;
        }, delay);
        
        if(!func.id) {
            func.apply(_this, _args);
        }
    }
}
复制代码

这是立即执行防抖,即触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。

函数节流throttle

流就是函数像水那样哗哗的执行

Demo

let input = document.getElementById('throttle');

input.addEventListener('keyup', function (e) {
    console.log(e.target.value);
})
复制代码

其实例子是一模一样的。。因为这两个方法都是为了解决函数触发的过于频繁这个问题

Resolve(时间戳+定时器)

function Log(value) {
    console.log(value);
}

function throttle(func, delay) {
    let last, delayTimer;
    return function (args) {
        let _this = this;
        let _args = args;
        let now = +new Date();
        if (last && now < last + delay) {
            clearTimeout(deferTimer);
            delayTimer = setTimeout(function () {
                last = now;
                func.apply(_this, _args);
            }, delay)
        } else {
            last = now;
            func.apply(_this,_args);
        }
    }
}

let throttleLog = throttle(Log, 500);

let input = document.getElementById('throttle');

input.addEventListener('keyup', function(e) {
    throttleLog(e.target.value);
})
复制代码

核心同样是throttle函数,这里用了闭包存储了两个变量last(最后执行时间)和delayTimer(延时函数),如果last存在(即该函数已经执行过),判断函数这次执行间隔是否超过delay,若不超过则清空延时器重新设置延时执行,若超过或者last不存在则直接执行函数,不管哪种判断结果都会将last设置为当前时间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值