函数节流,防抖区别于应用
函数防抖debounce
抖就是函数在那里抖个不停
Demo
let input = document.getElementById('debounce');
input.addEventListener('keyup', function (e) {
console.log(e.target.value);
})
复制代码
可以看到对于同样的输入,这里输出了很多次,对于这个例子来讲可能不会有太大问题,但是如果将console.log
换成ajax
请求的话,就会发出很多没有必要的请求;亦或者换成样式的变化,也会造成额外的Reflow
或Repaint
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
设置为当前时间