Interview AiBoxInterview AiBox 实时 AI 助手,让你自信应答每一场面试
请手写一个代码实现
题型摘要
防抖和节流是前端性能优化的两种关键技术。防抖确保函数只在事件停止触发后执行一次,适用于搜索联想等场景;节流确保函数以固定频率执行,适用于滚动事件等场景。两者都通过控制函数执行频率来优化性能,但实现原理和应用场景有所不同。防抖使用延迟执行+重置计时,节流使用固定时间间隔执行。理解它们的原理和实现方式,能帮助我们在实际开发中做出正确的选择。
防抖与节流函数的手写实现
在前端开发中,防抖(Debounce)和节流(Throttle)是两种常用的性能优化技术,用于控制函数的执行频率,特别是在处理频繁触发的事件如resize、scroll、input等场景中。
防抖函数(Debounce)
概念与原理
防抖函数的核心思想是:在事件被触发后,等待一定时间间隔后再执行函数,如果在这个时间间隔内事件再次被触发,则重新计时。这样可以确保函数只在用户停止操作后执行一次。
代码实现
/**
* 防抖函数
* @param {Function} fn 需要防抖的函数
* @param {number} delay 延迟时间,单位毫秒
* @param {boolean} immediate 是否立即执行
* @return {Function} 防抖后的函数
*/
function debounce(fn, delay = 300, immediate = false) {
let timer = null;
let isInvoke = false;
function _debounce(...args) {
if (timer) clearTimeout(timer);
if (immediate && !isInvoke) {
fn.apply(this, args);
isInvoke = true;
} else {
timer = setTimeout(() => {
fn.apply(this, args);
isInvoke = false;
timer = null;
}, delay);
}
}
_debounce.cancel = function() {
if (timer) clearTimeout(timer);
timer = null;
isInvoke = false;
}
return _debounce;
}
应用场景
- 搜索框输入联想:用户在输入过程中不频繁发送请求,只在停止输入后发送一次请求
- 按钮点击事件:防止用户多次快速点击导致重复提交
- 窗口resize事件:窗口调整结束后再执行相关操作
节流函数(Throttle)
概念与原理
节流函数的核心思想是:在一定时间间隔内只执行一次函数,无论这个时间间隔内事件触发了多少次。这样可以确保函数以固定的频率执行。
代码实现
/**
* 节流函数
* @param {Function} fn 需要节流的函数
* @param {number} interval 时间间隔,单位毫秒
* @param {Object} options 配置项
* @param {boolean} options.leading 是否在开始时立即执行
* @param {boolean} options.trailing 是否在结束时执行最后一次
* @return {Function} 节流后的函数
*/
function throttle(fn, interval = 300, options = { leading: true, trailing: true }) {
let timer = null;
let lastTime = 0;
const { leading, trailing } = options;
function _throttle(...args) {
const nowTime = Date.now();
// 首次执行或不立即执行的情况
if (!lastTime && !leading) lastTime = nowTime;
const remainTime = interval - (nowTime - lastTime);
if (remainTime <= 0) {
if (timer) {
clearTimeout(timer);
timer = null;
}
fn.apply(this, args);
lastTime = nowTime;
return;
}
if (trailing && !timer) {
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
lastTime = leading ? Date.now() : 0;
}, remainTime);
}
}
_throttle.cancel = function() {
if (timer) clearTimeout(timer);
timer = null;
lastTime = 0;
}
return _throttle;
}
应用场景
- 页面滚动事件:控制滚动事件的触发频率,提高性能
- 鼠标移动事件:如拖拽、跟随效果等
- 播放进度条:定期更新播放进度
- 高频点击事件:限制点击频率
防抖与节流的对比
| 特性 | 防抖(Debounce) | 节流(Throttle) |
|---|---|---|
| 执行时机 | 事件停止触发后一段时间 | 固定时间间隔内执行一次 |
| 执行次数 | 可能只执行一次 | 至少执行一次,可能多次 |
| 适用场景 | 只关心最终结果 | 关心过程和结果 |
| 实现原理 | 延迟执行+重置计时 | 固定时间间隔执行 |
使用示例
// 防抖示例:搜索框输入联想
const searchInput = document.getElementById('search');
const searchDebounce = debounce(function(e) {
console.log('发送搜索请求:', e.target.value);
// 实际项目中这里可能是API请求
}, 500);
searchInput.addEventListener('input', searchDebounce);
// 节流示例:页面滚动事件
const scrollThrottle = throttle(function() {
console.log('页面滚动位置:', window.scrollY);
// 实际项目中这里可能是加载更多内容或更新UI
}, 200);
window.addEventListener('scroll', scrollThrottle);
防抖与节流的可视化理解
实现细节解析
防抖函数实现要点
- 使用闭包保存计时器:确保每次调用的是同一个计时器
- 清除之前的计时器:每次触发事件时清除之前的计时器,重新计时
- 立即执行选项:通过
immediate参数控制是否在第一次触发时立即执行 - 取消功能:提供
cancel方法可以取消待执行的防抖函数
节流函数实现要点
- 时间戳判断:通过记录上一次执行的时间戳,判断是否达到执行间隔
- 计时器补充:对于最后一次触发,使用计时器确保执行
- 首尾执行控制:通过
leading和trailing参数控制是否在开始和结束时执行 - 取消功能:提供
cancel方法可以取消待执行的节流函数
进阶实现:结合requestAnimationFrame
对于动画相关的场景,可以使用requestAnimationFrame实现更高效的节流函数:
function rafThrottle(fn) {
let locked = false;
return function(...args) {
if (locked) return;
locked = true;
requestAnimationFrame(() => {
fn.apply(this, args);
locked = false;
});
};
}
// 使用示例
const moveThrottle = rafThrottle(function(e) {
console.log('鼠标移动:', e.clientX, e.clientY);
});
document.addEventListener('mousemove', moveThrottle);
总结
防抖和节流是前端性能优化的重要手段,它们通过控制函数执行频率来提高应用性能。防抖适合"只关心结果"的场景,如搜索联想;节流适合"关心过程"的场景,如滚动加载。理解它们的原理和实现方式,能够帮助我们在实际开发中做出正确的选择。
参考资料
思维导图
Interview AiBoxInterview AiBox — 面试搭档
不只是准备,更是实时陪练
Interview AiBox 在面试过程中提供实时屏幕提示、AI 模拟面试和智能复盘,让你每一次回答都更有信心。
AI 助读
一键发送到常用 AI
防抖和节流是前端性能优化的两种关键技术。防抖确保函数只在事件停止触发后执行一次,适用于搜索联想等场景;节流确保函数以固定频率执行,适用于滚动事件等场景。两者都通过控制函数执行频率来优化性能,但实现原理和应用场景有所不同。防抖使用延迟执行+重置计时,节流使用固定时间间隔执行。理解它们的原理和实现方式,能帮助我们在实际开发中做出正确的选择。
智能总结
深度解读
考点定位
思路启发
相关题目
请做一个自我介绍
自我介绍是面试的开场环节,应遵循"三段式"结构:基本信息与教育背景、核心能力与项目经验、求职动机与个人特质。重点突出与岗位相关的技能和经验,用具体数据和成果支撑,保持真诚自然的表达,控制在2-3分钟内。针对不同公司和岗位进行个性化调整,展示自己的匹配度和价值。
你有什么问题想问我们公司或团队的吗?
面试结尾提问是展示面试者思考深度和职业素养的重要机会。应提前准备3-5个有深度的问题,围绕团队技术、个人成长、公司文化和业务发展四个方面。好的问题能体现你对公司的了解、对职位的重视以及你的职业规划,避免问基础信息类问题。
请做一个自我介绍
自我介绍应遵循“我是谁-我为什么能胜任-我为什么想来”的逻辑框架。在“能胜任”部分,要通过STAR法则和量化结果来突出技术亮点和项目经验。在“想来”部分,要表达对华为技术、文化或业务的认同,展现匹配度和诚意。整个过程应简洁有力,控制在1-3分钟内。
请做一个自我介绍
自我介绍是面试的开场环节,应简洁明了地展示个人基本信息、教育背景、项目经验、技术特长、个人特质和求职动机。优秀的自我介绍应结构清晰、重点突出,与应聘岗位高度匹配,并表达出对公司的了解和加入的强烈意愿。
请做一个自我介绍,包括你的技术背景、项目经验和学习方向。
自我介绍应包含四个核心部分:个人背景、技术能力、项目经验和学习规划。技术背景需突出前端技术栈掌握程度;项目经验应选择代表性案例,说明技术实现和个人贡献;学习方向要体现职业规划与公司发展的契合度。整体表达应简洁有力,重点突出,时间控制在3-5分钟内。