文章目录
手写防抖debounce
debounce背景
若页面中有一个输入框<input type= "text" />
,我想根据输入框的内容变化实时做出变化。
那我该怎么做呢?
- 监听该输入框,文字变化后触发 change 事件
- 若直接用 keyup 事件,则会频繁触发 change 事件
那么从性能优化的角度要怎么做呢?
当用户输入结束或者暂停时,才会触发 change 事件
这就是防抖了
手写代码debounce
<input type="text" id="input1">
<script>
const input1 = document.getElementById('input1');
function debounce(fn, delay = 500) {
// 默认的delay是 500,若不给参数赋值的话
// timer 是在闭包中的
let timer = null;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
// 这里使用箭头函数,this和arguments从外继承来,若使用普通函数则需用词法作用域
fn.apply(this, arguments)
}, delay);
}
}
input1.addEventListener('keyup', debounce(function () {
//因为使用箭头函数,所以this指向上下文,此时this和input1相同,所以input1.value和this.value的值相同,arguments用于获取具体按下的键
console.log(this.value);
console.log(arguments);
}, 600));
</script>
防抖究竟想做到什么?
触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
就好像在百度搜索时,每次输入之后都有联想词弹出,这个控制联想词的方法就不可能是输入框内容一改变就触发的,他-定是当你结束输入一段时间之后才会触发。
也就是说
防抖策略是
将 高频操作合并为一次执行,并且每次高频 操作都清空定时器,只认最后一次操作。
手写节流throttle
throttle背景
若页面中有一个可拖拽的div<div id="div1" draggable="true"></div>
,当div绑定的触发事件有很多时(可能有大于百个的事件),我想每隔固定的时间触发一次,避免造成电脑卡顿。
那我该怎么做呢?
- 要保持一定频率触发,而不是随时触发
- 直接用 拖拽(drag)事件,则会频繁触发,很容易导致卡顿
那么从性能优化的角度要怎么做呢?
无论拖拽的速度有多快,都会 每隔 100ms(自定) 触发一次
这就是节流了
手写代码throttle
function throttle(fn, delay = 500) {
let timer = null;
return function () {
if (timer) {
return;
}
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, delay);
}
}
div1.addEventListener('drag', throttle(function (e) {
// 比如返回 div 的坐标值
console.log(e.offsetX, e.offsetY);
}))
节流究竟想做到什么?
高频事件触发,在n秒内只会执行一次,所以节流会稀释函数的执行频率。
举例:预定一个函数只有在大于等于执行周期时才执行,周期内调用不执行。就好像你在淘宝抢购某一件限量热卖商品时,你不断点刷新点购买,可是总有一段时间你点 上是没有效果,这里就用到了节流,就是怕点的太快导致系统出现bug。
也就是说
节流策略是
将高频操作按周期执行,一个 timeout 周期内执行一次,如果第一个周期执行完,有新的操作进来进行另一个周期。
节流和防抖的区别
防抖是将多次执行变为最后一次执行, 节流是将多次执行变成每隔一段时间执行。