函数去抖与节流
Debounce:函数去抖就是对于一定时间段的连续的函数调用,只让其执行一次
Throttle:函数节流就是让连续执行的函数,变成固定时间段间断地执行
区别:节流函数不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数。
debounce
浏览器的一些原生事件,在执行时并不是只执行一次,可能会执行很多次,因此需要我们对其加以控制。以scroll举例:
window.onscroll = function() {
console.log('hello world!');
}
因此,如果执行一些复杂的运算或者DOM操作,对于一些浏览器来说可能会出现崩溃的情况。
去抖debounce实现的效果是:以scroll举例,当scroll执行一次后,会设置一个定时器来控制接下来的一段时间内scroll不会被触发,如果这段时间内又触发了scroll,会在当前时间点重新设置定时器,知道定时器时间结束后才可以被继续触发。因此,debounce保证了一段时间内的连续函数调用,会使其只执行一次。
function debounce(delay, fn) {
var timer;
return function() {
var context = this;
var args = arguments;
if(timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(context, args);
}, delay)
}
}
function print() {
console.log('hello world!');
}
window.onscroll = debounce(2000, print);
上段代码的一个问题是,事件会在定时器结束后被触发,因此会出现一定的延迟,如果想让事件被立即触发,可以使用以下的去抖函数:
function debounce(delay, fn) {
var timer;
return function() {
var context = this;
var args = arguments;
if(timer) {
clearTimeout(timer);
}
var doNow = !timer;
timer = setTimeout(() => {
timer = null;
}, delay);
if(doNow) {
fn.apply(context, args);
}
}
}
但是,对于去抖来说,在某些场景下是不合适的,因此我们可以使用节流。
throttle
节流可以保证在一段时间内函数必定会触发一次。
节流主要有两种实现:
1.时间戳
2.定时器
// 时间戳实现
function throttle(delay, fn) {
var prev = Date.now();
return function() {
var curr = Date.now();
if(curr - prev > delay) {
fn.apply(this, arguments);
last = curr;
}
}
}
// 定时器实现
function throttle(delay, fn) {
var timer;
return function() {
var context = this; // 函数执行上下文
var args = arguments;
console.log('1', new Date());
if(timer) {
return;
}
timer = setTimeout(() => {
fn.apply(context, args);
clearTimeout(timer);
// setTimeout返回一个整数,clearTimeout后也还是整数,因此需要置空,setInterval也是如此
timer = null;
}, delay);
}
}
总结
防止一个事件频繁出发回调函数的方式:
去抖debounce: 一段时间内连续的函数调用,只允许其执行一次。原理是,维护一个定时器,只有定时器结束才可以继续触发事件。
节流throttle: 一段时间内的函数调用,保证事件一定会被执行一次。原理是判断两次执行函数的时间间隔是否大于延迟的时间。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。