节流和防抖都是为了节省计算机资源,防止高频率的执行函数。
节流:在指定的时间间隔内,只会执行一次任务;
防抖:任务频繁触发的情况下,只有任务触发的间隔超过指定的时间间隔,任务才会执行。
节流比较好理解,如果任务被频繁触发,比如浏览器窗口的改变,指定一个时间间隔,那么无论任务触发得有多频繁,在那个时间间隔里只会执行一次任务。
防抖,简单地说就是设定一个时间间隔,在这个时间间隔内无论触发多少次,都不会执行任务,而一旦停止触发,超过这个时间间隔,就会执行一次任务,也就是说只在最后一次的触发后才会执行任务。
节流代码:
function throttle(fn, timeout) {
let canRun = true; // 通过闭包保存一个标记
console.log("start")
return function () {
console.log("record")
// 在函数开头判断标记是否为true,不为true则return
if (!canRun) return;
// 立即设置为false
canRun = false;
console.log("resizing")
// 将外部传入的函数的执行放在setTimeout中
setTimeout(() => {
// 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。
// 当定时器没有执行的时候标记永远是false,在开头被return掉
fn.apply(this, arguments);
canRun = true;
}, timeout);
};
}
function sayHi(e) {
console.log(e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener("resize", throttle(sayHi, 1500));
在浏览器中改变窗口:
解释:start只会打印一次,在窗口改变期间会一直打印record,在停止改变窗口的1500ms里只会打印一次resizing。
防抖代码
function debounce(fn) {
let timeout = null; // 创建一个标记用来存放定时器的返回值
console.log("start")
return function () {
console.log("resizing")
// 每当用户输入的时候把前一个 setTimeout clear 掉
clearTimeout(timeout);
// 然后又创建一个新的 setTimeout, 这样就能保证interval 间隔内如果时间持续触发,就不会执行 fn 函数
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, 500);
};
}
// 处理函数
function handle() {
console.log(Math.random());
}
// 滚动事件
window.addEventListener("resize", debounce(handle));
在浏览器中改变窗口:
解释:start只会打印一次,在窗口改变期间会一直打印resizing,而在停止改变窗口后的500ms才会打印出随机数