防抖
-
在事件被触发后 n 秒再执行回调,如果在这 n 秒内又被触发,则重新计时
-
实现
/**
* 防抖
* 在事件被触发后 n 秒再执行回调,如果在这 n 秒内又被触发,则重新计时
* @param {*} fn
* @param {*} wait
*/
let timer = null;
function debounce(fn, wait) {
return function () {
let context = globalThis;
let args = arguments;
if (timer) {
clearTimeout(timer);
timer = null;
}
// n 秒之后执行
timer = setTimeout(() => {
// 使 fn 返回的 this 指向不变,并能接收到原有的参数
fn.apply(context, args);
}, wait);
}
}
- 测试
function log(data) {
console.log(data || 'default');
console.timeEnd('time');
}
console.time('time');
debounce(log, 1000)()
setTimeout(debounce(() => { log('hello') }, 1000), 500);
运行结果
节流
- 在一个单位时间内只能触发一次,如果这个单位时间内触发多次,只执行第一次
- 实现
/**
* 节流
* 在一个单位时间内只能触发一次,如果这个单位时间内触发多次,只执行第一次
*/
// 方法一:通过时间戳计算实现
let previous = 0;
function throttle(fn, delay) {
return function () {
let context = this;
let args = arguments;
let now = Date.now();
if (now - previous > delay) {
fn.apply(context, args);
previous = now;
}
}
}
// 方法二:通过定时器实现
let timer = null;
function throttle1(fn, delay) {
return function () {
let context = this;
let args = arguments;
let canRun = !timer;
timer = setTimeout(() => {
timer = null;
}, delay);
canRun && fn.apply(context, args);
}
}
- 测试
function log(data) {
console.log(data || '111');
}
throttle(() => { log('t0') }, 700)();
setTimeout(throttle(() => log('hello'), 700), 500);
throttle1(() => { log('t1') }, 700)();
setTimeout(throttle1(() => log('world'), 700), 500);
运行结果