前端面试之实践案例50题及参考答案
一、性能优化相关
1. 图片懒加载的实现思路
思路:监听滚动事件,判断图片是否进入视口,进入后再加载真实图片地址。可使用 Intersection Observer API
更高效实现。 伪代码:
1. 给img标签设置data-src属性存储真实地址,src属性使用占位图
2. 创建IntersectionObserver实例,配置阈值和根边界
3. 遍历所有需要懒加载的图片,让观察器观察每个图片
4. 在回调函数中,当图片进入视口时,将data-src的值赋给src属性
5. 图片加载完成后,停止观察该图片
2. 函数节流(throttle)的实现思路
思路:确保函数在指定时间间隔内只执行一次。 伪代码:
1. 定义上次执行时间变量lastExecTime
2. 返回一个新函数,接收函数执行所需的参数
3. 获取当前时间currentTime
4. 如果currentTime - lastExecTime >= 延迟时间,则执行原函数并更新lastExecTime
5. 否则,忽略本次调用或安排稍后执行
3. 函数防抖(debounce)的实现思路
思路:函数在连续触发时,只在最后一次触发后指定时间执行。 伪代码:
1. 定义定时器变量timer
2. 返回一个新函数,接收函数执行所需的参数
3. 清除已存在的timer
4. 设置新的timer,在延迟时间后执行原函数
5. 如果立即执行选项为true,则先立即执行一次再设置定时器
4. 前端性能优化常用手段
核心思路:
- 减少HTTP请求:合并CSS/JS文件,使用雪碧图,利用HTTP/2多路复用
- 资源压缩:使用Gzip/Brotli压缩,压缩图片(CWebP/AVIF),压缩JS/CSS/HTML
- 缓存策略:合理设置强缓存(Cache-Control)和协商缓存(ETag/Last-Modified)
- 延迟加载:非关键资源使用懒加载,如图片、组件、路由
- 代码分割:使用Webpack等工具按路由/功能拆分代码,动态导入
- CDN加速:静态资源部署到CDN
5. 内存泄漏检测与处理
常见内存泄漏场景:
- 未移除的事件监听器
- 闭包持有外部变量引用
- 未清除的定时器
- 全局变量引用
- DOM元素引用未释放
检测方法:
- 使用Chrome DevTools的Memory面板拍摄堆快照对比
- 使用Performance面板记录内存变化
- 第三方工具如Heapdump、MemLab
二、网络请求相关
6. 实现AJAX请求的封装
思路:封装XMLHttpRequest或fetch,提供统一接口处理请求、响应和错误。 伪代码:
1. 创建请求函数,接收url、method、data等参数
2. 设置默认请求头和参数
3. 使用Promise封装异步请求
4. 处理请求数据和响应数据转换
5. 统一处理HTTP状态码错误和网络错误
6. 提供超时控制和取消请求能力
7. 实现请求重试机制
思路:当请求失败时,自动重试指定次数,可加入指数退避策略。 伪代码:
1. 定义最大重试次数和当前重试计数
2. 封装请求函数,在catch中判断是否需要重试
3. 如果重试计数未超过最大值,等待一段时间后重试
4. 每次重试等待时间可指数增长(指数退避)
5. 重试达到最大次数后抛出最终错误
8. 实现前端缓存策略
思路:使用内存缓存、localStorage或sessionStorage缓存数据,减少网络请求。 伪代码:
1. 创建缓存对象,设置最大缓存数量和过期时间
2. 实现set方法,存储数据并记录存储时间
3. 实现get方法,检查数据是否存在及是否过期
4. 实现remove方法,删除指定缓存
5. 实现clear方法,清空过期或所有缓存
6. 可实现LRU(最近最少使用)淘汰策略
9. 实现大文件分片上传
思路:将大文件分割成小块,分片上传,支持断点续传。 伪代码:
1. 计算文件总大小和分片数量
2. 为每个分片生成唯一标识
3. 按顺序或并行上传分片
4. 每个分片上传成功后,记录上传进度
5. 全部上传完成后,请求服务端合并分片
6. 中断后可从已上传分片继续上传
10. 实现WebSocket断线重连
思路:监听WebSocket连接状态,断开时自动重连。 伪代码:
1. 创建WebSocket连接
2. 监听onclose事件,触发重连逻辑
3. 使用指数退避策略控制重连间隔
4. 记录重试次数,限制最大重试次数
5. 连接成功后重置重试计数器
三、JavaScript核心概念
11. 实现Promise.all
思路:接收Promise数组,全部成功时返回结果数组,任何一个失败则立即失败。 伪代码:
1. 返回新Promise
2. 检查输入是否为可迭代对象
3. 初始化结果数组和完成计数器
4. 遍历Promise数组,为每个Promise添加then/catch
5. 每个Promise完成时,将结果存入对应位置
6. 当所有Promise都完成时,resolve结果数组
7. 任何一个Promise失败时,立即reject
12. 实现Promise.race
思路:接收Promise数组,第一个完成(成功或失败)的Promise决定结果。 伪代码:
1. 返回新Promise
2. 检查输入是否为可迭代对象
3. 遍历Promise数组,为每个Promise添加then/catch
4. 当任何一个Promise完成时,立即resolve/reject
13. 实现深拷贝函数
思路:递归拷贝对象的所有属性,处理循环引用和特殊数据类型。 伪代码:
1. 处理基本数据类型直接返回
2. 处理Date、RegExp等特殊对象
3. 使用WeakMap解决循环引用问题
4. 获取对象所有属性(包括Symbol属性)
5. 递归拷贝每个属性
6. 根据对象类型创建新实例(Object/Array/Set/Map等)
14. 实现数组扁平化
思路:将多维数组转换为一维数组。 伪代码:
// 方法1:递归
1. 创建空结果数组
2. 遍历原数组每个元素
3. 如果当前元素是数组,递归调用扁平化函数
4. 否则,将元素添加到结果数组
// 方法2:使用reduce
1. 使用reduce遍历数组
2. 如果当前元素是数组,递归调用扁平化函数并concat
3. 否则,将元素添加到累加器
// 方法3:使用ES2019 flat方法
1. 直接使用arr.flat(Infinity)
15. 实现函数柯里化
思路:将多参数函数转换为一系列单参数函数。 伪代码:
1. 保存原始函数和预设参数
2. 返回新函数,接收新参数
3. 合并预设参数和新参数
4. 如果参数数量足够,调用原始函数
5. 如果参数不足,返回新的柯里化函数继续接收参数
四、框架相关
16. 实现简单的Virtual DOM
思路:用JavaScript对象表示DOM结构,通过diff算法比较变化,批量更新真实DOM。 伪代码:
1. 定义虚拟节点结构(type, props, children)
2. 实现虚拟DOM创建函数(createElement)
3. 实现虚拟DOM渲染函数(render),将虚拟节点转为真实DOM
4. 实现diff算法,比较两棵虚拟DOM树的差异
5. 实现patch函数,将差异应用到真实DOM
17. 实现双向数据绑定
思路:数据变化自动更新视图,视图变化自动更新数据。 伪代码:
1. 定义数据模型,使用Object.defineProperty或Proxy设置getter/setter
2. 实现编译器,解析模板中的指令和插值表达式
3. 实现观察者,监听数据变化,通知更新视图
4. 实现依赖收集,建立数据与视图的依赖关系
5. 监听表单元素输入事件,更新数据模型
18. 实现前端路由
思路:监听URL变化,根据路由映射渲染对应组件。 伪代码:
// Hash路由
1. 监听hashchange事件
2. 获取当前hash值,匹配对应组件
3. 渲染组件,更新页面内容
// History路由
1. 监听popstate事件
2. 拦截a标签点击和表单提交,使用history.pushState/replaceState
3. 根据pathname匹配对应组件
4. 渲染组件,更新页面内容
19. 实现状态管理库(Redux模式)
思路:单一数据源,状态只读,使用纯函数修改。 伪代码:
1. 定义store类,包含state、reducer、listeners
2. 实现getState方法,返回当前状态
3. 实现dispatch方法,接收action,执行reducer更新状态
4. 实现subscribe方法,注册状态变化监听器
5. 状态变化时通知所有监听器
20. 实现高阶组件(HOC)
思路:函数接收组件作为参数,返回增强功能的新组件。 伪代码:
1. 定义高阶函数,接收原始组件作为参数
2. 返回新组件,包装原始组件
3. 在新组件中添加额外功能(如数据获取、权限检查)
4. 将接收的props传递给原始组件
5. 返回增强后的组件
五、浏览器与DOM操作
21. 实现事件委托
思路:将事件监听器绑定到父元素,利用事件冒泡处理子元素事件。 伪代码:
1. 给父元素添加事件监听器
2. 在事件处理函数中,检查event.target
3. 根据target的属性或选择器判断目标元素
4. 执行相应的处理逻辑
5. 可添加选择器过滤,只处理特定子元素的事件
22. 实现拖拽功能
思路:监听鼠标事件,计算元素位置变化。 伪代码:
1. 监听拖拽元素的mousedown事件,记录初始位置
2. 监听document的mousemove事件,计算移动距离
3. 更新元素位置(left/top或transform)
4. 监听document的mouseup事件,移除事件监听器
5. 处理边界检测,防止元素拖出可视区域
23. 实现复制到剪贴板
思路:使用Clipboard API或document.execCommand实现复制功能。 伪代码:
// 现代方法(Clipboard API)
1. 使用navigator.clipboard.writeText(text)
2. 返回Promise,处理成功和错误情况
// 传统方法
1. 创建textarea元素,设置value为要复制的文本
2. 将textarea添加到document中
3. 选中textarea中的文本
4. 使用document.execCommand('copy')
5. 移除textarea元素
24. 实现文件上传预览
思路:使用FileReader读取文件内容,在页面上显示预览。 伪代码:
1. 监听input[type="file"]的change事件
2. 获取选中的文件列表
3. 遍历文件,根据文件类型处理预览
4. 图片文件使用FileReader.readAsDataURL转为DataURL
5. 设置img元素的src为DataURL
6. 其他类型文件可显示文件信息和图标
25. 实现全屏功能
思路:使用Fullscreen API控制元素进入/退出全屏模式。 伪代码:
// 进入全屏
1. 检查document.fullscreenEnabled支持情况
2. 调用element.requestFullscreen()
// 退出全屏
1. 检查document.fullscreenElement是否存在
2. 调用document.exitFullscreen()
// 监听全屏变化
1. 监听document的fullscreenchange事件
2. 根据全屏状态更新UI
六、工程化与架构
26. 实现模块加载器
思路:动态加载JavaScript模块,管理模块依赖关系。 伪代码:
1. 定义模块缓存对象
2. 实现require函数,根据模块名加载模块
3. 处理模块依赖,递归加载依赖模块
4. 执行模块代码,将导出内容存入缓存
5. 返回模块导出内容
27. 实现错误监控系统
思路:捕获前端错误,收集错误信息,上报到服务器。 伪代码:
1. 监听window的error和unhandledrejection事件
2. 收集错误信息(消息、堆栈、文件名、行号等)
3. 添加用户和环境信息(UA、URL、时间等)
4. 使用图片信标或fetch上报错误数据
5. 设置采样率,避免过多上报
28. 实现性能监控系统
思路:收集前端性能数据,计算核心性能指标。 伪代码:
1. 使用Performance API获取导航计时、资源计时数据
2. 计算核心Web指标(LCP、FID、CLS)
3. 使用PerformanceObserver监听性能条目
4. 收集自定义性能指标(业务相关)
5. 上报性能数据到分析服务器
29. 实现日志系统
思路:分级日志管理,支持控制台输出和远程上报。 伪代码:
1. 定义日志级别(debug、info、warn、error)
2. 实现日志函数,根据级别过滤日志
3. 格式化日志内容,添加时间戳和上下文
4. 支持控制台输出和远程上报
5. 实现日志队列和批量上报,避免频繁请求
30. 实现权限控制系统
思路:管理用户权限,控制页面元素和功能的访问。 伪代码:
1. 定义权限列表和角色权限映射
2. 实现权限检查函数,验证用户是否有权限
3. 实现指令/组件,根据权限显示/隐藏元素
4. 实现路由守卫,拦截无权限的导航
5. 从服务器获取用户权限信息
七、综合场景题
31. 实现无限滚动列表
思路:监听滚动位置,动态加载和渲染数据。 伪代码:
1. 计算容器高度和滚动位置
2. 监听scroll事件(可使用Intersection Observer)
3. 当滚动接近底部时,加载更多数据
4. 渲染新数据到列表末尾
5. 使用虚拟化技术优化大量数据渲染性能
32. 实现图片编辑器基础功能
思路:使用Canvas API实现图片裁剪、滤镜等功能。 伪代码:
// 图片加载
1. 使用Image对象加载图片
2. 绘制图片到canvas
// 裁剪功能
1. 获取裁剪区域坐标和尺寸
2. 使用drawImage裁剪图片
3. 输出裁剪后的图片
// 滤镜功能
1. 使用getImageData获取像素数据
2. 遍历像素,应用滤镜算法
3. 使用putImageData更新canvas
33. 实现实时搜索功能
思路:监听输入变化,发送搜索请求,展示搜索结果。 伪代码:
1. 监听输入框的input事件(可使用防抖)
2. 获取搜索关键词,验证有效性
3. 发送搜索请求到服务器(可使用缓存)
4. 渲染搜索结果列表
5. 处理无结果和错误情况
34. 实现颜色选择器
思路:使用Canvas或CSS实现颜色选择界面,输出颜色值。 伪代码:
1. 使用canvas绘制颜色光谱
2. 监听canvas的点击/拖拽事件,获取颜色值
3. 实现RGB/HSL/HEX颜色模型转换
4. 显示当前选择颜色和值
5. 支持颜色历史记录
35. 实现Markdown编辑器
思路:将Markdown文本转换为HTML并实时预览。 伪代码:
1. 分割屏幕:编辑区和预览区
2. 监听编辑区输入变化(可使用防抖)
3. 解析Markdown文本为HTML
4. 使用DOM操作或innerHTML更新预览区
5. 实现语法高亮(可使用第三方库)
八、算法与数据处理
36. 实现大数据列表渲染优化
思路:使用虚拟滚动技术,只渲染可见区域的项目。 伪代码:
1. 计算容器高度和滚动位置
2. 计算可见项目的起始和结束索引
3. 只渲染可见项目,使用绝对定位定位到正确位置
4. 监听scroll事件,更新可见区域
5. 使用占位元素保持滚动条正确
37. 实现数据序列化与反序列化
思路:将数据结构转换为字符串,以及从字符串重建数据结构。 伪代码:
// 序列化(JSON.stringify增强版)
1. 处理循环引用(使用WeakMap)
2. 处理特殊数据类型(Date、RegExp、Set、Map等)
3. 处理undefined、Function、Symbol等JSON不支持的类型
// 反序列化(JSON.parse增强版)
1. 解析JSON字符串
2. 根据特殊标记重建特殊对象
3. 恢复循环引用关系
38. 实现模板引擎
思路:解析模板语法,将数据和模板结合生成HTML。 伪代码:
1. 定义模板语法(变量、条件、循环等)
2. 使用正则表达式解析模板
3. 编译模板为JavaScript函数
4. 执行函数,传入数据,生成HTML
5. 处理XSS防护,转义特殊字符
39. 实现数据差异比较
思路:比较两个对象或数组的差异,生成变更记录。 伪代码:
1. 处理基本类型直接比较
2. 处理数组差异(新增、删除、移动、修改)
3. 处理对象差异(新增、删除、修改属性)
4. 递归比较嵌套对象
5. 生成结构化差异结果
40. 实现数据校验库
思路:定义校验规则,验证数据是否符合规则。 伪代码:
1. 定义校验规则(必填、类型、格式、长度等)
2. 实现校验函数,接收数据和规则
3. 遍历规则,验证每个字段
4. 收集所有错误信息
5. 返回校验结果(是否通过,错误详情)
九、安全与加密
41. 实现XSS防护
思路:对用户输入进行过滤和转义,防止脚本注入。 伪代码:
1. 识别潜在危险字符(<、>、&、"、'等)
2. 使用HTML实体编码转义危险字符
3. 对URL进行验证,防止javascript:协议
4. 使用CSP(内容安全策略)添加额外保护层
5. 避免使用innerHTML,使用textContent代替
42. 实现CSRF防护
思路:验证请求来源,使用Token防止跨站请求伪造。 伪代码:
1. 服务器生成CSRF Token并发送给客户端
2. 客户端将Token存储在cookie或localStorage
3. 客户端发送请求时携带Token( header或表单字段)
4. 服务器验证Token有效性
5. 使用SameSite cookie属性添加额外保护
43. 实现数据加密存储
思路:使用加密算法对敏感数据进行加密后存储。 伪代码:
1. 选择加密算法(如AES、RSA)
2. 生成或获取加密密钥
3. 加密前进行数据序列化
4. 使用加密算法加密数据
5. 存储加密后的数据和初始化向量(IV)
6. 解密时使用相同密钥和算法
44. 实现权限验证中间件
思路:在请求处理前验证用户权限。 伪代码:
1. 定义权限验证函数
2. 获取用户身份信息(token/session)
3. 验证token有效性
4. 查询用户权限列表
5. 检查用户是否有请求资源的权限
6. 无权限时返回错误,有权限时继续处理
45. 实现输入验证与清理
思路:验证用户输入合法性,清理潜在危险内容。 伪代码:
1. 定义字段验证规则(类型、长度、格式等)
2. 对每个输入字段应用验证规则
3. 移除或转义HTML标签和特殊字符
4. 验证数字范围、邮箱格式、URL格式等
5. 返回清理后的数据和错误信息
十、新技术与API
46. 实现Service Worker离线缓存
思路:使用Service Worker拦截网络请求,提供离线缓存功能。 伪代码:
1. 注册Service Worker
2. 在install事件中缓存关键资源
3. 在fetch事件中拦截请求
4. 检查缓存中是否有请求资源
5. 有则返回缓存,无则请求网络并缓存
6. 在activate事件中清理旧缓存
47. 实现Web Worker计算任务
思路:使用Web Worker在后台线程执行耗时计算。 伪代码:
// 主线程
1. 创建Worker实例,指定脚本文件
2. 使用postMessage发送数据给Worker
3. 监听message事件接收Worker返回结果
4. 使用terminate终止Worker
// Worker线程
1. 监听message事件接收主线程数据
2. 执行计算任务
3. 使用postMessage返回结果给主线程
48. 实现Web Audio音频处理
思路:使用Web Audio API处理和分析音频。 伪代码:
1. 创建AudioContext
2. 创建音频源(MediaElementSource或Oscillator)
3. 创建效果节点(Gain、Filter、Delay等)
4. 连接音频节点形成处理链
5. 分析音频数据(使用AnalyserNode)
6. 控制播放和效果参数
49. 实现WebR视频通话
思路:使用WebRTC建立点对点视频连接。 伪代码:
1. 获取用户媒体设备(摄像头、麦克风)
2. 创建RTCPeerConnection
3. 交换SDP信令(offer/answer)
4. 交换ICE候选
5. 建立连接,传输音视频流
6. 处理连接状态和数据通道
50. 实现WebGL数据可视化
思路:使用WebGL渲染大量数据的高性能可视化。 伪代码:
1. 创建WebGL上下文
2. 编译着色器程序
3. 创建缓冲区,上传数据
4. 设置 uniforms和attributes
5. 执行绘制命令
6. 实现动画和交互控制