防抖 & 节流
2019-10-10 本文已影响0人
Eileen_1d88
防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时
说到防抖,如果代码中我自己使用的话,可能我会直接这样写:
var timer = null
var time = 500
function f(fn) {
if (timer) {
clearTimeout(timer)
timer = null
}
timer = setTimeout(() => {
fn.apply(this, arguments)
}, time)
}
但是这样写的问题是非常明显的,代码毫无优雅性可言,并且一旦全局变量不小心被修改,这个函数就很可能无法正常执行,那么在这个基础上,我们可以一步步来完成一个防抖debounce。
思路:
1)首先我们明确知道我们需要传入的参数是一个fn和wait
2)那么我们还有一个timer,很明显,这个timer对于传入的fn是一个全局变量,那么为了在一个function中始终能访问到这个变量timer,注定我们需要使用一个闭包来完成
var debounce = function(fn, wait) {
var timeout = null;
return function() {
if (timeout) {
clearTimeout(timeout)
timeout = null
}
timeout = setTimeout(() => {
fn.apply(this, arguments)
}, wait)
}
};
节流:当持续触发事件时,保证一定时间段内只调用一次事件处理函数
也就是说在一段时间内,这段时间内最后被触发的操作会被执行
首先来一个最挫的实现:
var delay = 500
var timer
function f(fn) {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
那么继续按照方才的思路来:
1)要传的参数有2个: fn和delay
2)同样timer是fn要访问的全局变量
var throttle = function(fn, delay) {
var timer = null;
return function() {
var args = arguments
// 写的过程中在这里卡了一下,然后才反应过来,
// 有timer的时候,后续的代码完全没有执行,所以取到的参数是
// 第一次触发时的参数
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, args)
timer = null
}, delay)
}
}
};
写完这个之后,突然有一个感悟,有时候想写一个闭包的时候,可以先写一个很挫的不是闭包的函数来实现,然后再改成闭包的形式,现在觉得是这样,不知道是不是通用的,因为还没有懂得函数科里化😭