防抖、节流
防抖(debounce
)
所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
function debounce(fn, wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(context, args);
}, wait);
}
}
function debounce(fn, wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
let callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait);
if (callNow) fn.apply(context, args);
}
}
function debounce(fn, wait, immediate = true) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
let callNow = !timeout; // 根据 timer 是否为 null 来判断是否要执行 fn.
timeout = setTimeout(() => {
timeout = null;
}, wait);
if (callNow) fn.apply(context, args);
} else {
timeout = setTimeout(() => {
fn.apply(context, args);
}, await)
}
}
}
节流(throttle
)
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
function throttle (fn, wait) {
let previous = 0;
return function () {
let now = Date.now();
let context = this;
let args = arguments;
/* 返回函数一直在被调用,但是只有 now - previoust > wait 时,才会调用 fn */
if (now - previous > wait) {
fn.apply(context, args);
previous = now;
}
}
}
function throttle (fn, wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
fn.apply(context, args);
}, wait);
}
}
}
function throttle(fn, wait, immediate = true) {
if (immediate) {
// 注意: var
var previous = 0;
} else {
// 注意: var
var timeout;
}
return function () {
let context = this;
let args = arguments;
if (immediate) {
let now = Date.now(); // 获取当前时间戳
if (now - previous > wait) {
fn.apply(context, args);
previous = now;
}
} else if (!immediate) {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
fn.apply(context, args);
}, wait);
}
}
}
}
function throttle(fn, wait = 500) {
let previous = 0
let timer = null
return function anonymous(...args) { // 匿名函数
const now = Date.now()
const remaining = wait - (now - previous)
if(remaining <= 0) {
clearTimeout(timer)
timer = null
previous = now
fn.call(this, ...args)
} else if(!timer) {
// 若间隔时间小于 500ms,此时只过去了 5ms ,那就需要再过 450ms 后再执行。
// 也就说,当前时间还没有超过设定的节流时间,那就需要知道需要等多久才可执行,此时设置一个定时器来定时执行。
timer = setTimeout(() => { // 注意是箭头函数
clearTimeout(timer)
timer = null
previous = Date.now()
fn.call(this, ...args)
}, remaining)
}
}
}