之前有写过节流和防抖,但是那个比较随意,是在写js的时候随手写的,没有考虑封装,别人使用的快感。
所以现在来封装一个。
其实节流和防抖的作用类似,只是有一些小的区别:
防抖是一端时间后才让你执行一次,而节流则是先让你执行一次然后再禁止执行一端时间。然后再执行。
防抖多用在定时器中让某些ui部件的更新频率不那么高,看得清它的更新。节流多用在输入框中,方式input事件被多次触发。
因为防抖模拟的是一端时间的延迟执行,所以也可以用于登录按钮,限制其网络请求。
封装他们用到了闭包的思想,闭包的作用是哈,手写一端节流防抖代码就一目了然。
节流:
html
<input type="text">
js
var input, inputHandler;
init();
function init() {
input = document.querySelector("[type=text]");
inputHandler = fangdou(inputHandler, 300);
input.addEventListener('input', inputHandler);
}
function jieliu(cb,timeout){
var ids;
return function(...args){
if(ids) return;
ids = setTimeout(()=>{
clearTimeout(ids);
ids=undefined;
cb.apply(null,args);
},timeout);
}
}
防抖:
function fandou(cb,timeout){
var ids;
return function(...args){
clearTimeout(ids);
ids = setTimeout(()=>{
ids=undefined;
cb.apply(null,args);
},timeout);
}
}
关于这段代码,有下面的解释:
inputHandler
先于防抖节流函数预解析,所以它那时候只是一个接收事件并打印的函数- 防抖节流函数形成了一个闭包,并返回了这个闭包后的函数
- 这个返回的函数替换了原来的
inputHandler
,这一步是为了节约操作,同时也是为了代码复用。假如有一天不用节流防抖,只需注释这一行就可以。 - 原先的
inputHandler
函数随着节流函数和防抖函数的执行完毕被销毁,但是它作为节流和防抖的局部变量,被闭包返回的函数所引用,因此它会在内存中产生一份拷贝父本。(内存泄露) - 随着input事件的频繁触发,都进入了return function的那个局部函数,那个函数会根据节流和防抖的特性进行响应的执行。例如:防抖。刚开始没有ids,所以当时间到会调用回调函数,从而使ids再次变成没有。
- ids这种变量,被保存到了函数执行堆栈中,不会污染全局变量。
还有个挺大的区别,看下面这段代码:
compare.js
function throttle(cb, timeout) {
var ids;
return function (...args) {
if (ids) return;
ids = setTimeout(() => {
clearTimeout(ids)
ids = undefined;
cb.apply(this, args);
}, timeout);
}
}
function fangdou(cb, timeout) {
var ids;
return function (...args) {
clearTimeout(ids);
ids = setTimeout(() => {
cb.apply(this, args);
}, timeout);
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./compare.js"></script>
</head>
<body>
<input type="text">
<script>
var input;
init();
function init() {
input = document.querySelector('input');
inputHandler = fangdou(inputHandler, 1000);
input.addEventListener('input', inputHandler);
}
function inputHandler(e) {
console.log(e.target.value);
}
</script>
</body>
</html>
```
如果你一直按的话,节流会一直不停的每隔一秒打印。防抖就一直不执行,直到你停止输入后一秒后才执行。