闭包
函数能够访问并记住其词法作用域,即使该函数在其定义作用域之外执行
function add() {
let count = 0;
return function () {
count++;
return count;
};
}
const counter = add();
counter(); // 1
counter(); // 2
counter(); // 3add 执行后本应销毁内部的 count ,但由于返回的内部函数 引用了 count ,count 被保存在闭包中,得以在多次调用中持续累加 :闭包 👉 在多次函数调用之间共享和保存状态
防抖 & 节流
防抖和节流都是一种优化手段,用来保证程序应对高并发场景,两者的核心目标都是:在高频触发的场景下,控制函数的执行时机。
防抖
就是即使操作多次触发,但是我们只处理最后一次,可以把防抖理解为:只要你还在操作,我就不执行;等你停下来一段时间,我再执行。
防抖常见于以下场景:
- 搜索框输入联想
- 输入校验
resize事件
resize是浏览器的一个 窗口尺寸变化事件。当用户进行以下操作时,都会触发
resize:
- 拖动浏览器窗口大小
- 最大化 / 还原窗口
- 改变设备方向(移动端横竖屏切换)
- 改变视口大小(如 DevTools 打开/关闭)
function debounce(fn, delay) {
// 准备一个“取消执行”的开关
let timer = null;
return function (...args) {
// 每次触发都先取消上一次
clearTimeout(timer);
// 重新约定:delay 之后再执行
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
const debouncedFn = debounce(search, 300);
//触发 → 清除定时器
//触发 → 清除定时器
//触发 → 清除定时器
//停止操作 → 执行函数节流
事件可以一直触发,但函数按固定频率执行
节流通常用于:
- 页面滚动(scroll)
- 拖拽(drag)
- 高频点击
function throttle(fn, delay) {
let timer = null;
return function (...args) {
if (timer) return;
timer = setTimeout(() => {
// 保持原本的 this 和参数
fn.apply(this, args);
// 释放锁
timer = null;
}, delay);
};
}
const throttled = throttle(fn, 1000);