您的位置:首页 > Web前端 > JavaScript

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

2020-07-14 06:13 281 查看

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

防抖 (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;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: