计算机基础面试题
本题库共收录 55 道面试题(基础 18 / 进阶 16 / 深入 7 / 架构 14)。 本文件收录计算机科学基础相关面试题,目标题量 150 道。 题型覆盖:概念题、场景设计题、系统设计题、工程化题、性能优化题、安全题、软技能题、综合开放题。 难度覆盖:基础、进阶、深入、架构。 每道题除标准参考答案外,另附口头回答版,便于面试时快速组织语言。
目录
基础题(8 道)
FB-53-CO-B-001:什么是时间复杂度和空间复杂度?如何分析?
题型:概念题 难度:🟡 进阶 岗位层级:高级 面试知识域:计算机科学 标签:时间复杂度、空间复杂度、算法分析、Big-O 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请解释时间复杂度和空间复杂度的概念,并说明如何分析一个算法。
参考答案: 时间复杂度:
- 描述算法执行时间随输入规模增长的变化趋势。
- 用大 O 表示法,如 O(1)、O(n)、O(n²)、O(log n)。
空间复杂度:
- 描述算法运行过程中额外占用内存随输入规模增长的变化趋势。
- 也包括大 O 表示法。
分析方法:
找出基本操作
- 循环体、递归调用、比较操作等。
统计执行次数
- 单层循环:O(n)。
- 双层嵌套循环:O(n²)。
- 二分查找:O(log n)。
忽略低阶项和常数
- O(2n + 100) = O(n)。
- O(n² + n) = O(n²)。
空间分析
- 变量、数组、递归栈、哈希表等。
常见复杂度:
| 复杂度 | 名称 | 示例 |
|---|---|---|
| O(1) | 常数 | 数组索引访问 |
| O(log n) | 对数 | 二分查找 |
| O(n) | 线性 | 遍历数组 |
| O(n log n) | 线性对数 | 快速排序平均 |
| O(n²) | 平方 | 冒泡排序 |
| O(2ⁿ) | 指数 | 递归穷举 |
注意:
- 时间复杂度看最坏情况或平均情况。
- 空间复杂度关注额外空间,不包括输入本身。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
时间复杂度看执行时间随输入增长,空间复杂度看额外内存。用大 O 表示,分析时找基本操作统计次数,忽略低阶和常数。常见 O(1)、O(log n)、O(n)、O(n²) 等。
FB-53-CO-B-002:数组和链表有什么区别?
题型:概念题 难度:🟢 基础 岗位层级:初级 / 高级 面试知识域:53 计算机基础 标签:数组、链表、顺序存储、链式存储 出现频率:高频 预计回答时长:3-5 分钟
题目描述: 请比较数组和链表在存储结构、访问、插入删除等方面的差异。
参考答案:
| 维度 | 数组 | 链表 |
|---|---|---|
| 存储 | 连续内存 | 离散节点,通过指针连接 |
| 访问 | 随机访问 O(1) | 顺序访问 O(n) |
| 插入/删除 | O(n)(需要移动元素) | O(1)(已知前驱) |
| 扩容 | 通常需要重新分配 | 动态分配 |
| 缓存友好 | 好 | 差 |
| 适用 | 读多写少、已知长度 | 写多读少、动态增长 |
链表类型:单链表、双向链表、循环链表。
前端应用:
- React/Vue 的虚拟 DOM diff 类似列表操作。
- Promise 链、LRU 缓存使用双向链表。
评分维度:
- 存储结构(30%):连续 vs 离散
- 操作复杂度(40%):访问、插入、删除
- 应用场景(30%):读多 vs 写多
常见错误:
- 认为链表插入删除总是 O(1),忽略查找前驱的时间。
- 忽略数组的 CPU 缓存优势。
延伸追问:
- 如何实现一个 LRU 缓存?
- 数组和链表在虚拟 DOM 中如何体现?
相关题目:
参考资源:
口头回答版:
数组是连续内存,随机访问 O(1),插入删除 O(n),缓存友好;链表是离散节点,访问 O(n),插入删除 O(1)。读多写少用数组,写多读少或动态增长用链表。前端 LRU、Promise 链常用链表。
FB-53-CO-B-003:栈和队列有什么区别?前端有哪些应用?
题型:概念题 难度:🟢 基础 岗位层级:初级 / 高级 面试知识域:53 计算机基础 标签:栈、队列、LIFO、FIFO 出现频率:高频 预计回答时长:3-5 分钟
题目描述: 请解释栈和队列的特性,并举例说明它们在前端开发中的应用。
参考答案:
- 栈(Stack):后进先出 LIFO。
- 应用:函数调用栈、浏览器历史回退、撤销操作、括号匹配、DFS。
- 队列(Queue):先进先出 FIFO。
- 应用:任务队列(Event Loop)、消息队列、BFS、缓冲流、打印队列。
特殊队列:
- 双端队列 Deque:两端都可进出。
- 优先队列 Priority Queue:按优先级出队,通常用堆实现。
前端应用:
- JS 执行栈、宏任务/微任务队列。
- React 的 Update Queue。
- 路由历史栈管理。
评分维度:
- 特性区分(40%):LIFO vs FIFO
- 应用场景(40%):函数栈、任务队列、BFS/DFS
- 前端联系(20%):Event Loop、路由、React Update Queue
常见错误:
- 把栈和队列混用,导致逻辑错误。
- 认为队列只能简单 FIFO,忽略优先队列。
延伸追问:
- 如何用栈实现队列?
- Event Loop 中的任务队列为什么要分宏任务和微任务?
相关题目:
参考资源:
口头回答版:
栈是后进先出 LIFO,队列是先进先出 FIFO。栈用于函数调用栈、撤销、DFS;队列用于任务队列、消息队列、BFS。前端中 JS 执行栈、Event Loop、React Update Queue、路由历史都用到它们。
FB-53-CO-B-004:哈希表的工作原理是什么?如何解决冲突?
题型:概念题 难度:🟢 基础 岗位层级:初级 / 高级 面试知识域:53 计算机基础 标签:哈希表、哈希冲突、链地址法、开放寻址法 出现频率:高频 预计回答时长:3-5 分钟
题目描述: 请说明哈希表的基本原理、冲突产生原因以及常见解决方法。
参考答案:
哈希表通过哈希函数把 key 映射到数组下标,实现近似 O(1) 的查找、插入、删除。
冲突:不同 key 经哈希函数得到相同下标。
解决方法:
- 链地址法(Separate Chaining):每个桶存链表/树,冲突元素链在一起。
- 开放寻址法(Open Addressing):冲突后按规则找下一个空位,如线性探测、二次探测、双重哈希。
负载因子:
- 元素数/桶数。过高时冲突增多,需要扩容/再哈希。
前端应用:
- JavaScript 对象/Map 底层使用哈希表。
- Vue/React 的 key 用于快速 diff。
- 缓存实现。
评分维度:
- 原理(30%):哈希函数、数组下标
- 冲突解决(40%):链地址法、开放寻址法
- 负载因子与应用(30%):扩容、JS Map、缓存
常见错误:
- 认为哈希表所有操作都严格 O(1),忽略冲突严重时会退化。
- 混淆链地址法和开放寻址法。
延伸追问:
- JavaScript 的 Object 和 Map 在哈希实现上有什么区别?
- 一致性哈希如何解决普通哈希扩容的问题?
相关题目:
参考资源:
口头回答版:
哈希表用哈希函数把 key 转成数组下标,实现 O(1) 查找。冲突是两个 key 映射到同一位置。解决有链地址法,桶里挂链表或树;开放寻址法,找下一个空位。负载因子高时要扩容。前端 JS Map、对象、缓存都用哈希表。
FB-53-CO-B-005:二叉树有哪些遍历方式?
题型:概念题 难度:🟢 基础 岗位层级:初级 / 高级 面试知识域:53 计算机基础 标签:二叉树、遍历、前序、中序、后序、层序 出现频率:中频 预计回答时长:3-5 分钟
题目描述: 请说明二叉树的前序、中序、后序、层序遍历方式及其实现思路。
参考答案:
- 前序遍历:根 -> 左 -> 右。
- 中序遍历:左 -> 根 -> 右。
- 后序遍历:左 -> 右 -> 根。
- 层序遍历:按层级从上到下、从左到右,通常用队列实现。
实现方式:
- 递归:代码简洁,但可能有栈溢出风险。
- 迭代:用栈模拟递归,或用队列做层序。
应用场景:
- 中序遍历 BST 得到有序序列。
- 前序遍历用于复制树、序列化。
- 后序遍历用于释放树、计算高度。
- 层序遍历用于 BFS、按层级输出。
评分维度:
- 四种遍历(50%):顺序
- 实现方式(30%):递归、迭代
- 应用(20%):BST、复制、BFS
常见错误:
- 混淆前序和中序顺序。
- 递归转迭代时栈操作顺序错误。
延伸追问:
- 如何根据前序和中序序列重建二叉树?
- Morris 遍历如何实现 O(1) 空间?
相关题目:
参考资源:
口头回答版:
二叉树前序是根左右,中序是左根右,后序是左右根,层序是按层用队列。递归实现简单,迭代用栈或队列。中序遍历 BST 得有序序列,层序用于 BFS。
FB-53-CO-B-006:常见排序算法有哪些?各自特点是什么?
题型:概念题 难度:🟢 基础 岗位层级:初级 / 高级 面试知识域:53 计算机基础 标签:排序算法、快排、归并、堆排、稳定性 出现频率:高频 预计回答时长:3-5 分钟
题目描述: 请比较常见排序算法的时间复杂度、空间复杂度和稳定性。
参考答案:
| 算法 | 平均时间 | 最坏时间 | 空间 | 稳定性 |
|---|---|---|---|---|
| 冒泡/选择/插入 | O(n²) | O(n²) | O(1) | 插入稳定 |
| 快速排序 | O(n log n) | O(n²) | O(log n) | 不稳定 |
| 归并排序 | O(n log n) | O(n log n) | O(n) | 稳定 |
| 堆排序 | O(n log n) | O(n log n) | O(1) | 不稳定 |
| 计数/基数/桶排序 | O(n+k) | O(n+k) | O(k) | 稳定 |
- 稳定性:相等元素排序后相对顺序是否改变。
- 内部排序/外部排序:数据是否全部在内存中。
前端应用:
- 大多数语言内置 sort 使用快排或 Timsort(稳定)。
- 大数据量排序可放后端或 Web Worker。
评分维度:
- 算法对比(50%):时间、空间、稳定性
- 稳定性理解(20%):相等元素顺序
- 选型能力(30%):根据场景选择
常见错误:
- 认为快排一定比归并快,忽略稳定性需求。
- 对大数据量仍用 O(n²) 排序。
延伸追问:
- JavaScript Array.prototype.sort 使用什么算法?
- 如何对 1000 万条数据排序?
相关题目:
参考资源:
口头回答版:
常见排序:冒泡选择插入 O(n²),快排平均 O(n log n) 最坏 O(n²) 不稳定,归并 O(n log n) 稳定但 O(n) 空间,堆排 O(n log n) 不稳定 O(1) 空间。计数/基数适合特定数据。稳定性看相等元素相对顺序是否不变。
FB-53-CO-B-007:二分查找的适用条件和实现要点是什么?
题型:概念题 难度:🟢 基础 岗位层级:初级 / 高级 面试知识域:53 计算机基础 标签:二分查找、有序数组、边界条件 出现频率:高频 预计回答时长:3-5 分钟
题目描述: 请说明二分查找的前提条件、时间复杂度,并写出基本实现思路。
参考答案:
适用条件:
- 数据必须有序。
- 支持随机访问(数组)。
- 通常用于查找目标值或边界。
时间复杂度:O(log n)。
实现要点:
- 初始化
left = 0, right = n - 1。 - 循环条件
left <= right。 - 计算中间位置避免溢出:
mid = left + Math.floor((right - left) / 2)。 - 根据比较结果调整 left/right。
- 注意边界:查找左边界/右边界时循环条件和更新方式不同。
变形:
- 查找第一个/最后一个等于 target 的位置。
- 查找旋转排序数组的最小值。
评分维度:
- 前提条件(30%):有序、随机访问
- 复杂度(20%):O(log n)
- 实现细节(30%):循环条件、mid 计算、边界
- 变形(20%):左/右边界
常见错误:
- 在链表上使用二分查找。
- 循环条件和边界更新不匹配,导致死循环或遗漏。
延伸追问:
- 如何用二分查找求平方根?
- 旋转数组的二分查找怎么做?
相关题目:
参考资源:
口头回答版:
二分查找要求数据有序且能随机访问,时间 O(log n)。实现要定好左右指针,循环条件 left <= right,mid 用 left + (right-left)/2 防溢出。注意边界,左边界和右边界更新方式不同。
FB-53-CO-B-008:递归和迭代有什么区别?如何防止递归问题?
题型:概念题 难度:🟢 基础 岗位层级:初级 / 高级 面试知识域:53 计算机基础 标签:递归、迭代、栈溢出、尾递归 出现频率:中频 预计回答时长:3-5 分钟
题目描述: 请比较递归和迭代,并说明递归可能带来的问题及优化方法。
参考答案:
- 递归:函数调用自身,把问题分解为更小的子问题。
- 优点:代码简洁,自然适合树、分治。
- 缺点:调用栈开销大,深度过大导致栈溢出。
- 迭代:用循环和显式数据结构(栈/队列)模拟过程。
- 优点:空间可控,通常更高效。
- 缺点:代码可能更复杂。
递归问题及优化:
- 重复计算:用记忆化(Memoization)保存子问题结果。
- 栈溢出:
- 限制递归深度。
- 转换为迭代。
- 尾递归优化(部分引擎支持)。
- 时间复杂度高:动态规划将递归改为自底向上。
前端应用:
- 递归:树形组件渲染、JSON 深层遍历。
- 迭代:虚拟 DOM diff、广度优先搜索。
评分维度:
- 概念区别(40%):递归 vs 迭代
- 递归问题(30%):栈溢出、重复计算
- 优化方法(30%):记忆化、迭代、尾递归
常见错误:
- 递归没有终止条件导致死循环/栈溢出。
- 忽略递归的重复计算问题。
延伸追问:
- 尾递归优化是什么?JS 引擎支持吗?
- 递归深度过大时如何转为迭代?
相关题目:
参考资源:
口头回答版:
递归是函数调用自身,代码简洁但可能栈溢出;迭代用循环,空间可控。递归要防止重复计算用记忆化,防止栈溢出可以转迭代或用尾递归。前端树形组件常用递归,虚拟 DOM diff 常用迭代。
进阶题(8 道)
FB-53-CO-A-001:快速排序、归并排序、堆排序各有什么特点和适用场景?
题型:概念题 难度:🔵 进阶 岗位层级:高级 / 资深 面试知识域:53 计算机基础 标签:快排、归并、堆排、排序、分治 出现频率:高频 预计回答时长:5-7 分钟
题目描述: 请深入比较快速排序、归并排序、堆排序的原理、稳定性、适用场景。
参考答案:
快速排序:
- 原理:选基准,把数组分为小于基准和大于基准两部分,递归排序。
- 平均 O(n log n),最坏 O(n²)(数组已有序)。
- 空间 O(log n)(递归栈)。
- 不稳定。
- 适用:通用排序,平均性能好,cache 友好。
- 优化:三数取中、随机 pivot、尾递归优化、小数组插入排序。
归并排序:
- 原理:分治法,先分成两半排序,再合并。
- 稳定,时间 O(n log n)。
- 空间 O(n)。
- 适用:需要稳定性、链表排序、外部排序。
堆排序:
- 原理:建最大堆,每次把堆顶放到末尾,调整堆。
- 时间 O(n log n),空间 O(1)。
- 不稳定。
- 适用:内存受限、Top K 问题。
选型:
- 通用、追求平均速度:快排。
- 需要稳定:归并。
- 内存敏感/Top K:堆排。
评分维度:
- 原理理解(30%):分治、堆、合并
- 复杂度与稳定性(30%):时间、空间、稳定
- 适用场景(30%):通用、稳定、内存
- 优化(10%):快排优化
常见错误:
- 快排最坏情况未做优化。
- 需要稳定排序时误用快排。
延伸追问:
- 如何用快排思想找第 K 大元素?
- 为什么归并排序更适合链表?
相关题目:
参考资源:
口头回答版:
快排选基准分治,平均 O(n log n) 不稳定,适合通用;归并分治合并,稳定但 O(n) 空间,适合链表和外部排序;堆排序建堆调整,O(1) 空间,适合内存敏感和 Top K。需要稳定用归并。
FB-53-CO-A-002:图的基础遍历 BFS 与 DFS 有什么区别?
题型:概念题 难度:🔵 进阶 岗位层级:高级 / 资深 面试知识域:53 计算机基础 标签:图、BFS、DFS、广度优先、深度优先 出现频率:中频 预计回答时长:5-7 分钟
题目描述: 请比较图的 BFS 和 DFS 遍历,说明实现方式、时间复杂度和应用场景。
参考答案:
| 维度 | BFS | DFS |
|---|---|---|
| 数据结构 | 队列 | 栈(递归或显式栈) |
| 遍历顺序 | 按层扩展 | 一条路走到黑再回溯 |
| 空间复杂度 | O(V) 或 O(w)(w 为最大宽度) | O(h)(h 为深度) |
| 适用 | 最短路径、层级关系 | 连通性、拓扑排序、全排列 |
实现:
- BFS:从起点入队,访问邻居并入队,标记已访问。
- DFS:递归访问未访问邻居,或显式栈模拟。
时间复杂度:O(V + E)。
应用场景:
- BFS:无权图最短路径、社交网络一度/二度关系、层级遍历。
- DFS:迷宫、连通分量、拓扑排序、检测环。
前端应用:
- 依赖图解析(Webpack 模块依赖)。
- 组件树遍历。
- 权限菜单层级展开。
评分维度:
- 数据结构(30%):队列 vs 栈
- 遍历顺序(30%):层 vs 深度
- 复杂度(20%):O(V+E)
- 应用(20%):最短路径、连通性
常见错误:
- BFS/DFS 未标记已访问导致死循环。
- 认为 DFS 一定比 BFS 省空间。
延伸追问:
- 如何用 DFS 检测有向图中的环?
- BFS 在二叉树和图中实现有什么区别?
相关题目:
参考资源:
口头回答版:
BFS 用队列按层遍历,适合最短路径和层级关系;DFS 用栈或递归一路走到底再回溯,适合连通性、拓扑排序。时间都是 O(V+E)。前端依赖图解析、组件树遍历常用。
FB-53-CO-A-003:动态规划基础思想是什么?
题型:概念题 难度:🔵 进阶 岗位层级:高级 / 资深 面试知识域:53 计算机基础 标签:动态规划、DP、最优子结构、重叠子问题 出现频率:高频 预计回答时长:5-7 分钟
题目描述: 请解释动态规划的核心思想,并说明与递归/贪心的区别。
参考答案:
动态规划(DP)核心:
- 最优子结构:大问题最优解包含子问题最优解。
- 重叠子问题:不同大问题会重复用到相同子问题的解。
- 状态转移方程:定义状态并推导转移关系。
- 记忆化/自底向上:避免重复计算。
与递归:
- 递归可能重复计算,DP 用表记录子问题结果。
与贪心:
- 贪心每步局部最优,不回退;DP 全局最优,会考虑所有选择。
解题步骤:
- 定义状态。
- 找状态转移方程。
- 初始化边界。
- 确定遍历顺序。
- 可选空间优化。
常见题型:
- 背包、最长公共子序列、最长递增子序列、编辑距离、股票问题。
评分维度:
- 核心思想(40%):最优子结构、重叠子问题
- 与递归/贪心区别(30%):记忆化、全局最优
- 解题步骤(30%):状态、转移、初始化
常见错误:
- 状态定义不清晰导致转移方程写不出。
- 混淆 DP 和贪心。
延伸追问:
- 0/1 背包和完全背包的状态转移有什么区别?
- 如何对 DP 进行空间优化?
相关题目:
参考资源:
口头回答版:
动态规划核心是最优子结构和重叠子问题。把大问题拆成子问题,子问题结果复用。与递归比它记忆化避免重复;与贪心比它追求全局最优。解题先定义状态,找转移方程,初始化边界,再确定遍历顺序。
FB-53-CO-A-004:常见的字符串匹配算法有哪些?
题型:概念题 难度:🔵 进阶 岗位层级:高级 / 资深 面试知识域:53 计算机基础 标签:字符串匹配、KMP、Rabin-Karp、BF 出现频率:中频 预计回答时长:5-7 分钟
题目描述: 请比较暴力匹配、KMP、Rabin-Karp 等字符串匹配算法的原理和复杂度。
参考答案:
- 暴力匹配(BF):
- 逐位比较,不匹配时主串回溯一位。
- 时间 O(m×n)。
- KMP:
- 利用已匹配部分的最长相同前后缀(next 数组),避免主串回溯。
- 时间 O(m + n)。
- 适合单模式串匹配。
- Rabin-Karp:
- 用哈希比较子串,哈希冲突时逐位验证。
- 平均 O(m + n),最坏 O(m×n)。
- 适合多模式串匹配。
- Boyer-Moore / Sunday:
- 从右向左比较,利用坏字符/好后缀规则跳跃。
- 实际文本搜索中效率很高。
前端应用:
- 文本编辑器搜索、富文本关键词高亮。
- 路由匹配、正则表达式引擎。
评分维度:
- 算法原理(40%):BF、KMP、Rabin-Karp
- 复杂度(30%):时间、空间
- 应用(30%):单模式/多模式、文本搜索
常见错误:
- KMP 的 next 数组构建错误。
- 忽视 Rabin-Karp 的哈希冲突处理。
延伸追问:
- KMP 的 next 数组和 nextval 数组有什么区别?
- 如何实现一个文本编辑器的查找替换?
相关题目:
参考资源:
口头回答版:
暴力匹配逐位比,O(mn)。KMP 用 next 数组避免主串回溯,O(m+n)。Rabin-Karp 用哈希,平均快但最坏 O(mn),适合多模式。实际编辑器搜索常用 Boyer-Moore。前端用于文本高亮、路由匹配。
FB-53-CO-A-005:堆和优先队列有什么关系?
题型:概念题 难度:🔵 进阶 岗位层级:高级 / 资深 面试知识域:53 计算机基础 标签:堆、优先队列、完全二叉树、Top K 出现频率:中频 预计回答时长:5-7 分钟
题目描述: 请解释堆的数据结构,以及如何用堆实现优先队列,并举例应用。
参考答案:
堆:
- 特殊的完全二叉树。
- 大顶堆:父节点 ≥ 子节点;小顶堆:父节点 ≤ 子节点。
- 可用数组实现,索引 i 的左右子节点为 2i+1、2i+2。
优先队列:
- 元素带有优先级,出队顺序按优先级。
- 底层通常用堆实现,插入和弹出都是 O(log n)。
操作:
- 插入:放到末尾,向上调整(heapify-up)。
- 弹出堆顶:交换首尾,删除尾,向下调整(heapify-down)。
应用:
- Top K 问题(维护大小为 K 的小顶堆)。
- 合并 K 个有序数组。
- 任务调度(优先级队列)。
- Dijkstra 最短路径算法。
评分维度:
- 堆结构(30%):完全二叉树、数组表示
- 优先队列实现(30%):插入、弹出 O(log n)
- 应用(40%):Top K、任务调度、Dijkstra
常见错误:
- 认为堆只能找最大/最小,忽略可以动态插入删除。
- Top K 问题选错堆类型。
延伸追问:
- 如何用堆找海量数据中的中位数?
- 堆排序为什么不稳定?
相关题目:
参考资源:
口头回答版:
堆是完全二叉树,大顶堆父节点大于子节点,可用数组实现。优先队列通常用堆实现,插入和弹出 O(log n)。应用有 Top K、合并 K 个有序数组、任务调度、Dijkstra。Top K 问题用大小为 K 的小顶堆。
FB-53-CO-A-006:数据库索引和事务是什么?
题型:概念题 难度:🔵 进阶 岗位层级:高级 / 资深 面试知识域:53 计算机基础 标签:数据库、索引、B+树、事务、ACID 出现频率:高频 预计回答时长:5-7 分钟
题目描述: 请说明数据库索引的作用和常见结构,以及事务的 ACID 特性。
参考答案:
索引:
- 作用:加速查询,类似书的目录。
- 常见结构:
- B+ 树:平衡树,适合范围查询和等值查询,磁盘友好。
- 哈希索引:等值查询 O(1),不支持范围查询。
- 全文索引:搜索引擎场景。
- 代价:占用存储,写操作变慢,需要维护。
事务:
- 一组操作要么全成功要么全失败。
- ACID:
- Atomicity(原子性):要么全做,要么全不做。
- Consistency(一致性):数据完整性约束不被破坏。
- Isolation(隔离性):并发事务互不干扰。
- Durability(持久性):提交后数据不丢失。
隔离级别:读未提交、读已提交、可重复读、串行化。
前端联系:
- 理解索引有助于优化 API 查询、避免 N+1 查询。
- 事务保证业务操作一致性。
评分维度:
- 索引(40%):作用、B+树、哈希
- 事务 ACID(40%):四个特性
- 隔离级别(20%):读未提交到串行化
常见错误:
- 认为索引越多越好,忽略写性能。
- 把一致性和隔离性混淆。
延伸追问:
- 什么情况下索引会失效?
- 乐观锁和悲观锁有什么区别?
相关题目:
参考资源:
口头回答版:
数据库索引加速查询,常用 B+ 树适合范围查询,哈希索引适合等值查询。事务有 ACID:原子性、一致性、隔离性、持久性。隔离级别从读未提交到串行化。索引不是越多越好,写会变慢。
FB-53-CO-A-007:位运算有哪些常见技巧?
题型:概念题 难度:🔵 进阶 岗位层级:高级 / 资深 面试知识域:53 计算机基础 标签:位运算、位掩码、异或、权限设计 出现频率:中频 预计回答时长:5-7 分钟
题目描述: 请列举位运算的常见操作和应用场景。
参考答案:
常见位运算:
&(与):清零特定位、判断奇偶(n & 1)。|(或):设置标志位。^(异或):交换两数、找唯一出现奇数次的数。~(取反)。<</>>:左移右移,相当于乘除 2。
应用场景:
- 权限系统:用位掩码表示多个权限,如
READ=1, WRITE=2, EXEC=4。 - 状态压缩:用整数表示集合状态。
- 布隆过滤器:多个哈希函数映射到位数组。
- 图形处理:像素颜色通道操作。
- 算法优化:快速判断 2 的幂
(n & (n-1)) === 0。
注意:
- JavaScript 数字是 64 位浮点,位运算按 32 位有符号整数处理。
- 有符号右移
>>和无符号右移>>>区别。
评分维度:
- 位运算操作(40%):与或非异或移位
- 应用场景(40%):权限、状态压缩、布隆过滤器
- 语言特性(20%):JS 32 位处理
常见错误:
- 位运算优先级错误导致结果异常。
- 在 JS 中对超过 32 位的数做位运算。
延伸追问:
- 如何用位运算实现权限的增删查?
- 布隆过滤器的误判如何处理?
相关题目:
参考资源:
口头回答版:
位运算有与或非异或移位。应用包括权限位掩码、状态压缩、布隆过滤器、判断 2 的幂。JS 位运算按 32 位有符号整数处理。注意优先级和位数限制。
FB-53-CO-A-008:进程和线程有什么区别?
题型:概念题 难度:🔵 进阶 岗位层级:高级 / 资深 面试知识域:53 计算机基础 标签:进程、线程、并发、并行、上下文切换 出现频率:高频 预计回答时长:5-7 分钟
题目描述: 请比较进程和线程,包括资源分配、通信方式、切换开销等。
参考答案:
| 维度 | 进程 | 线程 |
|---|---|---|
| 资源 | 独立地址空间、代码、数据、堆栈 | 共享进程资源,独立栈和寄存器 |
| 切换开销 | 大(需要切换页表) | 小 |
| 通信 | IPC(管道、消息队列、共享内存、Socket) | 直接读写共享变量,需同步 |
| 崩溃影响 | 不影响其他进程 | 可能导致整个进程崩溃 |
| 调度单位 | 资源分配的基本单位 | CPU 调度的基本单位 |
并发 vs 并行:
- 并发:多个任务交替执行,宏观同时。
- 并行:多个任务真正同时执行(多核)。
前端联系:
- 浏览器多进程架构(渲染进程、GPU 进程、插件进程)。
- Web Worker 是独立线程,不阻塞主线程。
- Node.js 单线程事件循环,可通过 cluster/worker_threads 多线程。
评分维度:
- 资源与切换(30%):地址空间、切换开销
- 通信(30%):IPC、共享变量
- 并发并行(20%):概念区分
- 前端联系(20%):浏览器、Worker
常见错误:
- 认为线程完全独立,忽略共享内存带来的同步问题。
- 混淆并发和并行。
延伸追问:
- 浏览器为什么用多进程而不是多线程渲染?
- Web Worker 和 SharedArrayBuffer 有什么风险?
相关题目:
参考资源:
口头回答版:
进程有独立地址空间,切换开销大,通信用 IPC;线程共享进程资源,切换小,通信直接读写共享变量需同步。进程是资源分配单位,线程是调度单位。前端浏览器多进程,Web Worker 是独立线程。
深入题(7 道)
FB-53-CO-P-001:红黑树和 B+树各自有什么特点?
题型:概念题 难度:🟣 深入 岗位层级:资深 / 架构 面试知识域:53 计算机基础 标签:红黑树、B+树、平衡树、数据库索引 出现频率:中频 预计回答时长:7-10 分钟
题目描述: 请比较红黑树和 B+树的结构特点、操作复杂度和应用场景。
参考答案:
红黑树:
- 自平衡二叉搜索树,通过颜色约束保证树高 O(log n)。
- 插入、删除、查找都是 O(log n)。
- 实现相对复杂,但内存中效率很高。
- 应用:Java TreeMap、C++ map、Linux 完全公平调度器。
B+树:
- 多路平衡搜索树,所有数据存在叶子节点,叶子节点通过指针相连。
- 非叶子节点只存索引,降低磁盘 I/O。
- 适合磁盘存储和范围查询。
- 应用:数据库索引、文件系统。
对比:
| 维度 | 红黑树 | B+树 |
|---|---|---|
| 节点孩子数 | 2 | 多 |
| 存储介质 | 内存 | 磁盘 |
| 范围查询 | 需中序遍历 | 叶子链表直接遍历 |
| 磁盘友好 | 一般 | 优秀 |
评分维度:
- 红黑树(30%):自平衡、颜色约束、内存
- B+树(30%):多路、叶子链表、磁盘
- 对比(40%):范围查询、磁盘友好
常见错误:
- 认为红黑树适合数据库索引。
- 混淆 B 树和 B+树(B 树数据也可在非叶子节点)。
延伸追问:
- 为什么数据库索引不用红黑树而用 B+树?
- B+树在写入频繁时有什么劣势?
相关题目:
参考资源:
口头回答版:
红黑树是自平衡二叉搜索树,内存中 O(log n) 操作,实现复杂。B+树是多路平衡树,数据全在叶子并通过链表相连,适合磁盘和范围查询。数据库索引用 B+树因为它磁盘友好、范围查询快。
FB-53-CO-P-002:一致性哈希是什么?解决了什么问题?
题型:概念题 难度:🟣 深入 岗位层级:资深 / 架构 面试知识域:53 计算机基础 标签:一致性哈希、分布式、缓存、负载均衡 出现频率:中频 预计回答时长:7-10 分钟
题目描述: 请解释一致性哈希的原理,以及它在分布式系统中的作用。
参考答案:
问题:
- 普通哈希在节点数量变化时,几乎所有 key 的映射都会改变,导致大量缓存失效或数据迁移。
一致性哈希:
- 把节点和 key 都映射到一个环形哈希空间。
- 每个 key 顺时针找到第一个节点负责。
- 增加/删除节点只影响相邻区间,大部分 key 无需迁移。
虚拟节点:
- 为每个物理节点生成多个虚拟节点,均匀分散在环上,解决数据倾斜。
应用:
- 分布式缓存(Redis Cluster、Memcached)。
- 负载均衡(Nginx consistent hashing)。
- 分布式存储分片。
评分维度:
- 问题理解(30%):普通哈希扩容问题
- 原理(40%):哈希环、顺时针映射
- 虚拟节点与应用(30%):数据倾斜、缓存、负载均衡
常见错误:
- 认为一致性哈希完全不需要数据迁移。
- 不使用虚拟节点导致数据倾斜。
延伸追问:
- 一致性哈希和范围分片各适合什么场景?
- 虚拟节点数量如何选择?
相关题目:
参考资源:
口头回答版:
一致性哈希把节点和 key 放到一个哈希环上,key 顺时针找第一个节点。这样增删节点只影响附近 key,大部分缓存不失效。用虚拟节点解决数据倾斜。常用于分布式缓存、负载均衡和分片。
FB-53-CO-P-003:垃圾回收机制有哪些常见策略?
题型:概念题 难度:🟣 深入 岗位层级:资深 / 架构 面试知识域:53 计算机基础 标签:垃圾回收、GC、引用计数、标记清除、分代回收 出现频率:中频 预计回答时长:7-10 分钟
题目描述: 请说明常见的垃圾回收算法,以及它们的优缺点。
参考答案:
常见策略:
- 引用计数:对象被引用次数为 0 时回收。
- 优点:实时回收。
- 缺点:循环引用无法回收,计数维护有开销。
- 标记-清除(Mark-Sweep):从根对象出发标记可达对象,清除未标记对象。
- 优点:处理循环引用。
- 缺点:产生内存碎片,停顿时间长。
- 标记-整理(Mark-Compact):标记后将存活对象整理到一端,消除碎片。
- 优点:无碎片。
- 缺点:移动对象开销大。
- 复制(Copying):将存活对象复制到另一半空间,清空原空间。
- 优点:无碎片。
- 缺点:内存利用率 50%。
- 分代回收:对象按存活时间分为新生代、老年代,采用不同算法。
- 新生代:复制算法(存活率低)。
- 老年代:标记-清除/整理。
前端联系:
- V8 引擎使用分代回收 + 增量标记 + 并发标记。
- 避免内存泄漏:移除事件监听、清理定时器、避免闭包引用大对象。
评分维度:
- 算法覆盖(50%):引用计数、标记清除、复制、分代
- 优缺点(30%):碎片、循环引用、停顿
- 前端联系(20%):V8、内存泄漏
常见错误:
- 认为引用计数能处理循环引用。
- 忽略 GC 停顿对实时应用的影响。
延伸追问:
- V8 的 Orinoco 垃圾回收器有哪些优化?
- 如何排查前端内存泄漏?
相关题目:
参考资源:
口头回答版:
垃圾回收策略有引用计数、标记清除、标记整理、复制、分代回收。引用计数不能处理循环引用;标记清除会产生碎片;复制无碎片但内存利用率低;分代回收按存活时间用不同算法。V8 用分代加增量标记,前端要避免内存泄漏。
FB-53-CO-P-004:事件驱动与 IO 模型有哪些?
题型:概念题 难度:🟣 深入 岗位层级:资深 / 架构 面试知识域:53 计算机基础 标签:IO 模型、阻塞、非阻塞、多路复用、异步 IO 出现频率:中频 预计回答时长:7-10 分钟
题目描述: 请比较阻塞 IO、非阻塞 IO、IO 多路复用、信号驱动 IO、异步 IO 的特点。
参考答案:
IO 模型(UNIX 5 种):
- 阻塞 IO:调用后一直等待数据就绪并复制完成。
- 非阻塞 IO:调用立即返回,需轮询数据是否就绪。
- IO 多路复用:一个线程监听多个文件描述符,如 select/poll/epoll/kqueue。
- 信号驱动 IO:数据就绪时内核发信号通知。
- 异步 IO:内核完成数据复制后再通知应用,全程不阻塞。
对比:
| 模型 | 等待数据 | 数据复制 | 代表 |
|---|---|---|---|
| 阻塞 | 阻塞 | 阻塞 | 传统 socket |
| 非阻塞 | 轮询 | 阻塞 | 少量连接 |
| 多路复用 | 阻塞在 selector | 阻塞 | epoll、Node.js |
| 异步 | 不阻塞 | 不阻塞 | Windows IOCP、io_uring |
前端联系:
- Node.js 事件循环基于 epoll/kqueue 多路复用。
- 浏览器事件循环处理网络、用户事件。
评分维度:
- 五种模型(50%):阻塞、非阻塞、多路复用、信号、异步
- 对比(30%):等待与复制阶段
- 前端联系(20%):Node.js、浏览器
常见错误:
- 认为非阻塞 IO 就是异步 IO。
- 混淆 IO 多路复用和异步 IO。
延伸追问:
- epoll 相比 select 的优势是什么?
- Node.js 的异步 IO 是否真正完全异步?
相关题目:
参考资源:
口头回答版:
IO 模型分阻塞、非阻塞、IO 多路复用、信号驱动、异步。阻塞全程等;非阻塞轮询;多路复用一个线程监听多个 fd;异步全程不阻塞。Node.js 基于 epoll/kqueue 多路复用。非阻塞不等于异步。
FB-53-CO-P-005:编译原理基础对前端开发有什么帮助?
题型:概念题 难度:🟣 深入 岗位层级:资深 / 架构 面试知识域:53 计算机基础 标签:编译原理、AST、词法分析、语法分析、Babel 出现频率:中频 预计回答时长:7-10 分钟
题目描述: 请简述编译原理中的词法分析、语法分析、AST,并说明在前端工程化中的应用。
参考答案:
编译过程:
- 词法分析(Lexing):源代码 -> Token 流。
- 语法分析(Parsing):Token 流 -> AST(抽象语法树)。
- 语义分析:类型检查、作用域分析。
- 转换/优化:遍历 AST 做变换。
- 代码生成:AST -> 目标代码。
前端应用:
- Babel:把新语法 AST 转换为兼容语法。
- ESLint/TSLint:基于 AST 做静态分析。
- Webpack/Rollup:AST 用于 tree-shaking、代码压缩。
- Prettier:基于 AST 格式化代码。
- Vue/React 编译器:模板/JSX 编译为渲染函数。
AST 遍历:
- 访问者模式(visitor),进入/离开节点时执行操作。
评分维度:
- 编译过程(40%):词法、语法、语义、生成
- 前端应用(40%):Babel、ESLint、打包、编译器
- AST 遍历(20%):访问者模式
常见错误:
- 认为编译原理只是写编译器,忽略在工程化中的广泛应用。
- 混淆词法分析和语法分析。
延伸追问:
- 如何写一个简单的 Babel 插件?
- AST 和 CST 有什么区别?
相关题目:
参考资源:
口头回答版:
编译原理包括词法分析生成 Token、语法分析生成 AST、语义分析、转换优化、代码生成。前端中 Babel、ESLint、Webpack、Prettier、Vue/React 编译器都用 AST。遍历 AST 常用访问者模式。
FB-53-CO-P-006:设计模式在前端有哪些常见应用?
题型:概念题 难度:🟣 深入 岗位层级:资深 / 架构 面试知识域:53 计算机基础 标签:设计模式、单例、观察者、工厂、策略、适配器 出现频率:中频 预计回答时长:7-10 分钟
题目描述: 请列举前端开发中常见的设计模式,并说明各自的应用场景。
参考答案:
常见模式:
- 单例模式:全局唯一实例,如 Redux store、Vuex store、日志对象。
- 观察者模式/发布订阅:事件总线、Redux 订阅、Vue 响应式系统。
- 工厂模式:创建组件/对象,如 React.createElement、组件库按需创建。
- 策略模式:不同算法可替换,如表单校验规则、图表类型切换。
- 装饰器模式:增强对象功能,如高阶组件 HOC、ES 装饰器。
- 适配器模式:统一接口,如 API 适配层、数据格式转换。
- 代理模式:控制对象访问,如 Vue3 Proxy、ES Proxy 缓存。
- 命令模式:撤销/重做、队列任务。
- 组合模式:树形结构,如文件系统、组件树。
应用价值:
- 提高代码复用、可维护性、可扩展性。
- 但不要为了用模式而用模式。
评分维度:
- 模式覆盖(50%):能列举并解释 5 种以上
- 前端应用(30%):Redux、Vue、React、组件库
- 选型意识(20%):避免过度设计
常见错误:
- 只背模式定义,不会结合前端实例。
- 过度使用设计模式导致代码复杂。
延伸追问:
- Vue 的响应式系统用了哪些设计模式?
- 高阶组件和装饰器模式的关系?
相关题目:
参考资源:
口头回答版:
前端常用设计模式有单例、观察者、工厂、策略、装饰器、适配器、代理、命令、组合。Redux store 是单例,事件总线是观察者,HOC 是装饰器,Vue3 Proxy 是代理。不要为了用模式而过度设计。
FB-53-CO-P-007:TCP 和 UDP 有什么区别?
题型:概念题 难度:🟣 深入 岗位层级:资深 / 架构 面试知识域:53 计算机基础 标签:TCP、UDP、可靠传输、连接、网络 出现频率:高频 预计回答时长:7-10 分钟
题目描述: 请比较 TCP 和 UDP 的特性,并说明前端场景中的应用。
参考答案:
| 维度 | TCP | UDP |
|---|---|---|
| 连接 | 面向连接 | 无连接 |
| 可靠性 | 可靠,有序,重传 | 不可靠,无序 |
| 流量控制 | 有 | 无 |
| 拥塞控制 | 有 | 无 |
| 头部开销 | 大 | 小 |
| 传输效率 | 相对较低 | 高 |
| 适用 | 文件、网页、邮件 | 音视频、实时游戏、DNS |
TCP 机制:
- 三次握手建立连接,四次挥手断开。
- 序号与确认、超时重传、滑动窗口、拥塞控制。
前端应用:
- HTTP/HTTPS 基于 TCP。
- WebSocket 握手基于 TCP,之后全双工。
- WebRTC 媒体传输基于 UDP,信令可用 TCP/WebSocket。
- DNS 查询默认 UDP。
评分维度:
- TCP 特性(40%):连接、可靠、重传、窗口
- UDP 特性(30%):无连接、高效
- 前端应用(30%):HTTP、WebSocket、WebRTC、DNS
常见错误:
- 认为 UDP 完全不能用,忽略实时场景优势。
- 认为 TCP 一定比 UDP 慢,忽略可靠性需求。
延伸追问:
- 为什么 TCP 握手是三次而不是两次?
- WebRTC 中 UDP 如何保证音视频质量?
相关题目:
参考资源:
口头回答版:
TCP 面向连接、可靠有序、有流量和拥塞控制,适合网页文件;UDP 无连接、不可靠但开销小、效率高,适合音视频、实时游戏、DNS。前端 HTTP 和 WebSocket 基于 TCP,WebRTC 媒体用 UDP。
架构题(32 道)
FB-53-SD-R-001:如何设计一个短链服务?
题型:系统设计题 难度:🔴 架构 岗位层级:架构 / 专家 面试知识域:53 计算机基础 标签:短链、哈希、发号器、分布式、数据库 出现频率:高频 预计回答时长:10-15 分钟
题目描述: 请设计一个短链生成与解析服务,要求高性能、低冲突、可扩展。
参考答案:
核心功能:
- 长 URL -> 短码;短码 -> 长 URL 重定向。
短码生成方案:
- 哈希法:对长 URL 做 MD5/SHA 取前 7 位,冲突时加 salt 重试。
- 发号器:全局自增 ID,转 62 进制(a-zA-Z0-9)生成短码。
- 预生成:批量生成短码放入池子,避免高并发冲突。
存储:
- 关系型数据库 + 短码唯一索引。
- 缓存:Redis 存储热点短码,加速解析。
- 读写分离,解析为主读场景。
性能:
- 读多写少,CDN 缓存 302 重定向。
- 布隆过滤器防止缓存穿透。
- 解析时先查缓存,未命中再查库。
安全:
- 短码长度足够,防止遍历。
- 链接审核,防止钓鱼/恶意跳转。
- 访问限频、过期清理。
补充说明:
在实际落地 设计一个短链服务 时,建议结合 短链、哈希、发号器 的真实场景做验证。重点关注可观测性埋点、异常降级路径和性能基线回归;同时通过灰度发布、指标看板和复盘机制持续迭代,确保方案从“能跑”演进为“可维护、可扩展”。 评分维度:
- 短码生成(30%):哈希、发号器、预生成
- 存储与缓存(30%):数据库、Redis、CDN
- 性能(20%):读优化、布隆过滤器
- 安全(20%):防遍历、审核
常见错误:
- 直接用数据库自增 ID 导致短码可预测。
- 忽略缓存穿透和恶意遍历。
延伸追问:
- 短链服务如何实现自定义短码?
- 统计短链点击量如何设计?
相关题目:
参考资源:
口头回答版:
短链服务把长 URL 转成短码。生成可用哈希取前几位冲突重试,或发号器自增 ID 转 62 进制,或预生成短码池。存储用数据库加唯一索引,Redis 缓存热点,CDN 缓存重定向。要防遍历和恶意链接。
FB-53-SD-R-002:从系统架构角度如何设计一个秒杀系统?
题型:系统设计题 难度:🔴 架构 岗位层级:架构 / 专家 面试知识域:53 计算机基础 标签:秒杀、高并发、限流、库存、队列 出现频率:高频 预计回答时长:10-15 分钟
题目描述: 请设计一个秒杀系统,重点说明前端、网关、库存、订单等关键环节的设计。
参考答案:
前端:
- 静态化活动页,CDN 加速。
- 验证码/答题防刷。
- 按钮防抖、倒计时错峰。
- 降级预案:排队中、已售罄页面。
网关/接入层:
- Nginx 限流、黑名单、WAF。
- 请求校验:用户登录、资格、时间段。
- 削峰:令牌桶/漏桶。
业务层:
- 库存扣减前置到 Redis,使用 Lua 脚本保证原子性。
- 异步下单:扣减成功后发消息队列,订单服务异步处理。
- 数据库最终一致性,避免直接扛高并发写。
库存:
- 预热库存到 Redis。
- 扣减采用 decrement,归零后加布隆过滤器或标记,直接返回售罄。
- 允许少量超卖或采用预扣 + 回补。
订单:
- 消息队列削峰,按用户 ID 分片消费。
- 幂等控制,防止重复下单。
- 超时未支付释放库存。
监控:
- 实时 QPS、库存、下单成功率、错误率。
- 自动熔断降级。
评分维度:
- 前端设计(20%):静态化、防刷、降级
- 网关限流(20%):限流、校验、削峰
- 库存处理(30%):Redis、Lua、异步
- 订单与监控(30%):队列、幂等、熔断
常见错误:
- 直接让数据库扛秒杀流量。
- 库存扣减不做原子性保护。
延伸追问:
- 如何防止超卖?
- 秒杀结束后如何对账?
相关题目:
参考资源:
口头回答版:
秒杀系统前端要静态化加 CDN、验证码防刷、按钮防抖;网关做限流校验和削峰;库存放 Redis 用 Lua 原子扣减,成功后异步发队列下单;订单服务幂等、超时释放库存;全链路监控和熔断。不要让数据库直接扛流量。
FB-53-SD-R-003:如何设计一个实时排行榜?
题型:系统设计题 难度:🔴 架构 岗位层级:架构 / 专家 面试知识域:53 计算机基础 标签:排行榜、Redis、Sorted Set、实时、Top K 出现频率:中频 预计回答时长:10-15 分钟
题目描述: 请设计一个支持实时更新的排行榜系统,支持全服榜、好友榜、周榜等。
参考答案:
数据模型:
- 用户 ID -> 分数,支持同分按时间排序。
存储方案:
- Redis Sorted Set:
ZADD更新分数,ZREVRANGE取 Top N。- 时间复杂度 O(log n) 更新,O(log n + k) 查询 Top K。
- 持久化:定时或增量同步到数据库。
排行榜类型:
- 全服榜:一个全局 Sorted Set。
- 好友榜:用户 ID 集合与全局分数取交集(
ZINTERSTORE)。 - 周榜/月榜:按周期新建 key,过期后归档。
实时性:
- 事件触发更新(如得分后调用 ZADD)。
- 批量更新降低 Redis 压力。
- 对非关键榜单可定时聚合。
缓存与降级:
- 前端缓存排行榜快照,减少请求。
- 榜单过大时只展示前 N 名,支持分页。
- Redis 故障时降级为静态榜或空榜。
扩展:
- 分片:按用户 ID 或分数区间分片。
- 多数据中心:异步复制榜单数据。
评分维度:
- 存储选型(30%):Sorted Set
- 榜单类型(20%):全服、好友、周期榜
- 实时性(20%):事件触发、批量
- 缓存与扩展(30%):分页、分片、降级
常见错误:
- 用数据库 ORDER BY 实时计算全服榜。
- 排行榜 key 无过期策略,导致内存无限增长。
延伸追问:
- 如何处理同分用户的排名?
- 亿级用户排行榜如何分片?
相关题目:
参考资源:
口头回答版:
实时排行榜可用 Redis Sorted Set,ZADD 更新分数,ZREVRANGE 取 Top N。全服榜一个 key,好友榜用集合交集,周榜按月分 key。事件触发更新,批量降低压力,前端缓存快照,过大分页。Redis 故障降级。
FB-53-SD-R-004:高并发下的限流与降级策略如何设计?
题型:系统设计题 难度:🔴 架构 岗位层级:架构 / 专家 面试知识域:53 计算机基础 标签:限流、降级、熔断、高并发、稳定性 出现频率:中频 预计回答时长:10-15 分钟
题目描述: 请设计一套高并发场景下的限流、熔断、降级方案,保障核心功能可用。
参考答案:
限流:
- 计数器:固定窗口,简单但有临界突发。
- 滑动窗口:更平滑,但实现复杂。
- 漏桶:恒定速率处理,平滑突发。
- 令牌桶:允许一定突发,平均速率可控。
- 维度:全局、用户、IP、接口、业务。
- 实现:网关层(Nginx/OpenResty/Envoy)、应用层(Guava/Redis + Lua)。
熔断:
- 监测错误率/慢请求比例,超过阈值后快速失败。
- 半开状态探测恢复。
- 工具:Hystrix、Sentinel、Resilience4j。
降级:
- 非核心功能关闭或简化(如关闭推荐、返回静态数据)。
- 异步化非关键操作。
- 页面静态化、CDN 兜底。
协同:
- 限流防流量突增,熔断隔离故障,降级保核心。
- 监控告警 + 自动/手动触发。
评分维度:
- 限流算法(30%):计数器、滑动窗口、漏桶、令牌桶
- 熔断机制(30%):错误率、半开、恢复
- 降级策略(30%):核心功能、静态化、异步
- 协同与监控(10%):自动触发、告警
常见错误:
- 只做限流不做熔断,故障仍会拖垮系统。
- 降级策略影响核心功能。
延伸追问:
- 限流阈值如何设定?
- 熔断半开状态如何避免抖动?
相关题目:
参考资源:
口头回答版:
高并发下用限流、熔断、降级保稳定。限流有计数器、滑动窗口、漏桶、令牌桶,可在网关或应用层做。熔断看错误率,超阈值快速失败,半开探测恢复。降级关闭非核心功能,返回静态数据。三者协同,加监控告警。
FB-53-SD-R-005:分布式一致性基础有哪些?
题型:系统设计题 难度:🔴 架构 岗位层级:架构 / 专家 面试知识域:53 计算机基础 标签:分布式一致性、CAP、BASE、共识算法 出现频率:中频 预计回答时长:10-15 分钟
题目描述: 请说明分布式系统中的一致性级别,以及 CAP/BASE 定理和常见共识算法。
参考答案:
一致性级别:
- 强一致性:任何时刻所有节点数据一致。
- 最终一致性:不保证实时一致,但保证在一定时间后一致。
- 因果一致性:有因果关系的事件按顺序一致。
- 会话一致性:同一会话内一致。
CAP:
- Consistency、Availability、Partition Tolerance,三者最多取其二。
- 分布式系统通常优先 AP 或 CP。
BASE:
- Basically Available(基本可用)、Soft state(软状态)、Eventually consistent(最终一致)。
- 是 AP 系统的实践理论。
共识算法:
- Paxos/Raft:强一致,用于 etcd、ZooKeeper、Consul。
- Gossip:最终一致,用于 Cassandra、Redis Cluster。
- Quorum NWR:读写副本数权衡一致性。
前端影响:
- 数据同步延迟、冲突解决、离线编辑。
评分维度:
- 一致性级别(30%):强一致、最终一致、因果
- CAP/BASE(30%):取舍、实践
- 共识算法(30%):Paxos/Raft、Gossip、Quorum
- 前端联系(10%):延迟、冲突
常见错误:
- 认为 CAP 是三选二,实际上 P 必须满足,所以是 CA 中二选一。
- 所有系统都追求强一致,忽略可用性。
延伸追问:
- Raft 相比 Paxos 为什么更易理解?
- 前端如何实现最终一致的数据同步?
相关题目:
参考资源:
口头回答版:
分布式一致性分强一致、最终一致、因果一致等。CAP 说一致性、可用性、分区容错最多取其二,通常优先 AP 或 CP。BASE 是基本可用、软状态、最终一致。共识算法有 Paxos/Raft 强一致,Gossip 最终一致。前端要注意同步延迟和冲突。
FB-53-CP-R-001:技术选型中如何权衡算法与数据结构?
题型:综合开放题 难度:🔴 架构 岗位层级:架构 / 专家 面试知识域:53 计算机基础 标签:技术选型、算法、数据结构、性能、可维护性 出现频率:中频 预计回答时长:10-15 分钟
题目描述: 请结合实际项目,说明在架构设计中如何根据业务需求选择合适的算法和数据结构。
参考答案:
权衡维度:
- 数据规模:小数据简单结构即可;大数据需考虑时间/空间复杂度。
- 访问模式:读多写少(数组/哈希)、写多读少(链表/日志结构)、范围查询(B+树/Skip List)。
- 操作频率:高频路径用 O(1) 或 O(log n),低频可接受 O(n)。
- 一致性要求:强一致需要复杂同步,最终一致可简化。
- 可维护性:避免过度优化,代码应易读易测试。
- 团队能力:选择团队熟悉、生态成熟的方案。
案例:
- 用户会话缓存:哈希表 + TTL。
- 实时排行榜:Redis Sorted Set。
- 消息队列:数组/链表 + 持久化。
- 全文搜索:倒排索引。
- 路由匹配:Trie 树或正则。
反模式:
- 为极致性能引入复杂算法,导致难以维护。
- 忽视数据增长,初期选型后期无法满足。
评分维度:
- 权衡维度(40%):规模、访问模式、一致性、可维护性
- 案例分析(40%):能结合场景选型
- 反模式(20%):避免过度设计
常见错误:
- 只看时间复杂度,忽略实现复杂度和团队成本。
- 盲目使用高级数据结构。
延伸追问:
- 如何评估一个新算法是否值得引入?
- 当业务变化导致原选型不再适合时如何迁移?
相关题目:
参考资源:
口头回答版:
技术选型要根据数据规模、访问模式、操作频率、一致性、可维护性和团队能力。用户会话用哈希表,排行榜用 Sorted Set,全文搜索用倒排索引。不要为极致性能过度设计,要平衡性能和可维护性。
FB-53-CP-R-002:如何评估一个系统的可扩展性?
题型:综合开放题 难度:🔴 架构 岗位层级:架构 / 专家 面试知识域:53 计算机基础 标签:可扩展性、水平扩展、垂直扩展、容量规划 出现频率:中频 预计回答时长:10-15 分钟
题目描述: 请说明评估系统可扩展性的方法,以及如何设计一个可水平扩展的系统。
参考答案:
可扩展性维度:
- 水平扩展(Scale-out):加机器,适合无状态服务。
- 垂直扩展(Scale-up):升级单机配置,有上限。
- 功能扩展:新功能对现有系统影响小。
- 数据扩展:分库分表、分片。
评估方法:
- 压力测试,找到 QPS/TPS 上限。
- 容量规划,预测资源增长。
- 识别单点瓶颈(CPU、内存、IO、网络、数据库)。
- 混沌测试,验证故障下扩展能力。
设计原则:
- 无状态:业务逻辑不依赖本地状态。
- 分片:按用户/订单 ID 分片,避免热点。
- 负载均衡:均匀分发请求。
- 缓存:减少后端压力。
- 异步:削峰填谷。
- 服务解耦:微服务/模块化,独立扩展。
度量指标:
- 吞吐量、延迟 P99、错误率、资源利用率。
- 扩容后性能是否线性增长。
评分维度:
- 扩展维度(30%):水平、垂直、功能、数据
- 评估方法(30%):压测、容量规划、瓶颈识别
- 设计原则(30%):无状态、分片、缓存、异步
- 度量(10%):指标
常见错误:
- 只加机器不拆分瓶颈,扩展效果差。
- 忽视数据分片后的跨分片查询问题。
延伸追问:
- 如何识别系统中的热点数据?
- 分库分表后如何分页排序?
相关题目:
参考资源:
口头回答版:
可扩展性分水平扩展加机器、垂直扩展升级单机、功能扩展和数据分片。评估要做压测、容量规划、找瓶颈。设计要无状态、分片、负载均衡、缓存、异步、服务解耦。度量吞吐量、延迟、错误率和扩容线性度。
FB-53-CO-A-009:数组和链表有什么区别?各自适用什么场景?
题型:概念题 难度:🟡 进阶 岗位层级:高级 面试知识域:计算机科学 标签:数组、链表、数据结构、区别 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请说明数组和链表的区别及适用场景。
参考答案: 数组 vs 链表:
| 特性 | 数组 | 链表 |
|---|---|---|
| 内存布局 | 连续 | 不连续 |
| 访问 | 随机访问 O(1) | 顺序访问 O(n) |
| 插入/删除 | O(n),需要移动元素 | O(1),已知节点位置 |
| 扩容 | 需要重新分配内存 | 动态分配 |
| 缓存友好性 | 好 | 差 |
| 额外空间 | 少 | 需要指针空间 |
适用场景:
- 数组:频繁随机访问、大小固定、需要缓存友好。
- 链表:频繁插入删除、大小不确定、实现队列/栈。
变体:
- 链表:单链表、双链表、循环链表。
- 数组:动态数组(如 JS Array、Java ArrayList)。
示例:
- 数组实现二分查找。
- 链表实现 LRU Cache。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
数组连续内存,随机访问 O(1),插入删除 O(n),缓存好。链表不连续,插入删除 O(1),访问 O(n),缓存差。数组适合随机访问,链表适合频繁增删。
FB-53-CO-A-010:栈和队列有什么区别?有哪些应用?
题型:概念题 难度:🟡 进阶 岗位层级:高级 面试知识域:计算机科学 标签:栈、队列、数据结构、LIFO、FIFO 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请说明栈和队列的区别及典型应用。
参考答案: 栈(Stack):
- LIFO(Last In First Out,后进先出)。
- 操作:push、pop、peek。
- 应用:函数调用栈、表达式求值、括号匹配、DFS、撤销操作。
队列(Queue):
- FIFO(First In First Out,先进先出)。
- 操作:enqueue、dequeue、front。
- 应用:BFS、任务调度、消息队列、缓冲、打印队列。
扩展:
- 双端队列(Deque):两端都可以入队出队。
- 优先队列(Priority Queue):按优先级出队,常用堆实现。
示例:
- 浏览器前进后退:栈。
- 异步任务队列:队列。
- 滑动窗口最大值:双端队列。
- Top K 问题:优先队列。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
栈是 LIFO,用于函数调用、DFS、括号匹配;队列是 FIFO,用于 BFS、任务调度、消息队列。扩展有双端队列和优先队列。
FB-53-CO-A-011:哈希表(Hash Table)的原理是什么?如何解决冲突?
题型:概念题 难度:🟡 进阶 岗位层级:高级 面试知识域:计算机科学 标签:哈希表、冲突、拉链法、开放寻址法 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请说明哈希表的工作原理及常见冲突解决方法。
参考答案: 哈希表原理:
哈希函数
- 将 key 映射为数组下标。
- 好的哈希函数应均匀分布、计算快。
存储
- 根据哈希值将数据存入对应桶。
查找
- 计算 key 的哈希值,直接定位桶。
- 理想情况 O(1)。
冲突(Collision):
- 不同 key 映射到同一位置。
解决方法:
拉链法(Separate Chaining)
- 每个桶维护一个链表或其他结构。
- 冲突元素加入链表。
开放寻址法(Open Addressing)
- 冲突时按某种探测策略找下一个空桶。
- 线性探测、二次探测、双重哈希。
再哈希(Rehashing)
- 冲突严重时扩容并重新计算哈希。
公共溢出区
- 冲突元素放到单独区域。
注意:
- 负载因子(元素数/桶数)影响性能。
- 负载因子过高时需扩容。
- JS 的 Object/Map 底层使用哈希表。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
哈希表用哈希函数把 key 映射为下标,理想 O(1)。冲突可用拉链法、开放寻址法、再哈希。负载因子高时要扩容。
FB-53-CO-A-012:什么是二叉树、BST、AVL 树、红黑树?
题型:概念题 难度:🟡 进阶 岗位层级:高级 面试知识域:计算机科学 标签:二叉树、BST、AVL、红黑树、数据结构 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请说明二叉树、二叉搜索树、AVL 树、红黑树的概念和区别。
参考答案: 概念:
二叉树(Binary Tree)
- 每个节点最多两个子节点。
- 常见遍历:前序、中序、后序、层序。
二叉搜索树(BST)
- 左子树所有节点 < 根节点 < 右子树所有节点。
- 查找、插入、删除平均 O(log n),最坏 O(n)。
AVL 树
- 自平衡 BST。
- 任意节点左右子树高度差不超过 1。
- 查找快,但旋转操作多,插入删除较慢。
红黑树
- 近似平衡 BST。
- 通过五条颜色规则保持平衡。
- 插入删除旋转少,综合性能好。
- Java HashMap、C++ map、Linux 内核大量使用。
对比:
| 特性 | BST | AVL | 红黑树 |
|---|---|---|---|
| 平衡性 | 不一定 | 严格 | 近似 |
| 查找 | 平均 O(log n) | O(log n) | O(log n) |
| 插入删除 | 平均 O(log n) | O(log n),旋转多 | O(log n),旋转少 |
| 实现复杂度 | 简单 | 复杂 | 较复杂 |
应用:
- BST:简单有序数据。
- AVL:查找频繁的场景。
- 红黑树:综合操作频繁的场景。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
二叉树每个节点最多两个子节点;BST 左小右大;AVL 严格自平衡;红黑树近似平衡,旋转少。查找都 O(log n),AVL 查找快,红黑树综合好。
FB-53-CO-B-009:排序算法有哪些?各自的时间复杂度是多少?
题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:排序、算法、时间复杂度、稳定排序 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请列举常见排序算法及其时间复杂度和稳定性。
参考答案: 常见排序算法:
| 算法 | 平均时间 | 最坏时间 | 空间 | 稳定性 |
|---|---|---|---|---|
| 冒泡排序 | O(n²) | O(n²) | O(1) | 稳定 |
| 选择排序 | O(n²) | O(n²) | O(1) | 不稳定 |
| 插入排序 | O(n²) | O(n²) | O(1) | 稳定 |
| 希尔排序 | O(n log n) ~ O(n²) | O(n²) | O(1) | 不稳定 |
| 归并排序 | O(n log n) | O(n log n) | O(n) | 稳定 |
| 快速排序 | O(n log n) | O(n²) | O(log n) | 不稳定 |
| 堆排序 | O(n log n) | O(n log n) | O(1) | 不稳定 |
| 计数排序 | O(n + k) | O(n + k) | O(k) | 稳定 |
| 桶排序 | O(n + k) | O(n²) | O(n + k) | 稳定 |
| 基数排序 | O(d(n + k)) | O(d(n + k)) | O(n + k) | 稳定 |
选择建议:
- 数据规模小:插入排序。
- 需要稳定:归并排序。
- 平均性能最好:快速排序。
- 内存受限:堆排序。
- 数据范围小:计数排序/基数排序。
稳定性:
- 稳定排序保证相等元素相对顺序不变。
- 对象排序时常需要稳定。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
常见排序:冒泡、选择、插入是 O(n²);归并、快排、堆排是 O(n log n);计数、桶、基数是线性。归并稳定,快排平均好,堆排空间少。
FB-53-CO-B-010:深拷贝和浅拷贝有什么区别?前端如何实现?
题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:深拷贝、浅拷贝、JavaScript、对象复制 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请说明深拷贝和浅拷贝的区别,以及前端实现深拷贝的方法。
参考答案: 浅拷贝:
- 只复制对象的第一层属性。
- 嵌套对象仍然共享引用。
- 修改副本的嵌套对象会影响原对象。
深拷贝:
- 递归复制所有层级。
- 副本和原对象完全独立。
前端实现方式:
JSON 方法
jsconst copy = JSON.parse(JSON.stringify(obj));- 简单但无法处理函数、undefined、Date、RegExp、Map、Set、循环引用。
递归实现
jsfunction deepClone(obj, map = new WeakMap()) { if (obj === null || typeof obj !== 'object') return obj; if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); if (map.has(obj)) return map.get(obj); const clone = Array.isArray(obj) ? [] : {}; map.set(obj, clone); for (let key in obj) { if (obj.hasOwnProperty(key)) { clone[key] = deepClone(obj[key], map); } } return clone; }structuredClone
- 浏览器原生 API。
- 支持更多类型,但不支持函数。
lodash.cloneDeep
- 成熟库,处理各种边界情况。
选择:
- 简单对象:JSON 或 structuredClone。
- 复杂对象:递归实现或 lodash。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
浅拷贝只复制第一层,嵌套共享引用;深拷贝递归复制完全独立。前端可用 JSON.parse/stringify、递归、structuredClone、lodash.cloneDeep。
FB-53-CO-B-011:什么是闭包?有什么应用和注意事项?
题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:闭包、JavaScript、作用域、内存 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请解释闭包的概念,并说明其应用场景和注意事项。
参考答案: 闭包:
- 函数能够记住并访问其词法作用域,即使函数在其词法作用域之外执行。
- 闭包 = 函数 + 引用环境。
示例:
function createCounter() {
let count = 0;
return function() {
return ++count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2应用场景:
数据封装/私有变量
- 模拟类和私有属性。
函数工厂
- 创建配置化函数。
回调和异步
- 保持对创建时状态的引用。
柯里化
- 多参数函数转换为单参数链式调用。
防抖节流
- 保持计时器状态。
注意事项:
- 内存泄漏:闭包持有不再需要的引用。
- 循环中的闭包:注意变量共享问题(用 let 或 IIFE)。
- 调试困难:过多闭包使作用域链复杂。
最佳实践:
- 只在需要时使用闭包。
- 避免意外持有大对象。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
闭包是函数记住并访问其词法作用域的能力。用于数据封装、函数工厂、回调、柯里化、防抖节流。注意内存泄漏和循环中的变量共享。
FB-53-CO-B-012:什么是事件循环(Event Loop)?宏任务和微任务有什么区别?
题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:事件循环、Event Loop、宏任务、微任务、JavaScript 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请解释 JavaScript 的事件循环机制,以及宏任务和微任务的区别。
参考答案: 事件循环:
- JavaScript 是单线程语言,通过事件循环实现异步非阻塞。
- 事件循环不断检查调用栈和任务队列,将任务放入调用栈执行。
任务类型:
同步任务
- 直接放入调用栈执行。
宏任务(Macrotask)
- setTimeout、setInterval、setImmediate(Node)、I/O、UI 渲染。
- 每个事件循环周期执行一个宏任务。
微任务(Microtask)
- Promise.then/catch/finally、MutationObserver、queueMicrotask。
- 当前宏任务执行完后,立即执行所有微任务。
执行顺序:
- 执行同步代码。
- 执行所有微任务。
- 执行一个宏任务。
- 重复 2-3。
示例:
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
// 输出:1 4 3 2注意:
- 微任务优先级高于宏任务。
- 大量微任务可能阻塞渲染。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
事件循环让 JS 单线程异步执行。同步代码先执行,然后所有微任务,然后一个宏任务循环。微任务有 Promise.then,宏任务有 setTimeout。微任务优先级更高。
FB-53-CO-B-013:什么是原型链?JavaScript 的继承如何实现?
题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:原型链、继承、JavaScript、prototype、class 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请说明 JavaScript 原型链的概念及继承实现方式。
参考答案: 原型链:
- 每个对象都有
__proto__属性,指向其原型对象。 - 原型对象又有自己的原型,形成链式结构。
- 查找属性时沿原型链向上查找。
构造函数与原型:
- 函数有
prototype属性,指向原型对象。 - 实例的
__proto__指向构造函数的prototype。
继承方式:
原型链继承
jsChild.prototype = new Parent();- 缺点:共享引用类型属性。
构造函数继承
jsfunction Child() { Parent.call(this); }- 缺点:无法继承原型方法。
组合继承
- 构造函数继承 + 原型链继承。
寄生组合继承
- 最优方案:用 Object.create 连接原型。
ES6 Class
jsclass Child extends Parent { constructor() { super(); } }- 语法糖,底层仍是原型链。
注意:
instanceof检查原型链。Object.getPrototypeOf获取原型。- ES6 class 中
super()必须在this之前调用。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
原型链是对象通过 proto 链接到原型对象的链。继承可用原型链、构造函数、组合、寄生组合、ES6 class。class 是语法糖,底层仍是原型链。
FB-53-CO-B-014:什么是防抖(debounce)和节流(throttle)?
题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:防抖、节流、debounce、throttle、性能 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请解释防抖和节流的概念及适用场景。
参考答案: 防抖(Debounce):
- 在事件触发后等待一段时间,如果这段时间内没有再次触发,才执行函数。
- 如果连续触发,只执行最后一次。
- 适用:搜索输入、窗口 resize、表单验证。
节流(Throttle):
- 规定时间内只执行一次函数。
- 即使连续触发,也按固定频率执行。
- 适用:滚动加载、mousemove、按钮点击防重复。
对比:
| 特性 | Debounce | Throttle |
|---|---|---|
| 触发方式 | 停止触发后执行 | 按固定频率执行 |
| 执行次数 | 可能一次 | 多次 |
| 场景 | 输入搜索 | 滚动监听 |
实现:
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
function throttle(fn, interval) {
let last = 0;
return function(...args) {
const now = Date.now();
if (now - last >= interval) {
last = now;
fn.apply(this, args);
}
};
}注意:
- 要保留 this 和参数。
- 可考虑 leading/trailing 选项。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
防抖是停止触发后执行,只执行最后一次;节流是固定频率执行。防抖适合搜索输入,节流适合滚动监听。实现用 setTimeout 或时间戳。
FB-53-CP-R-003:前端如何实现 LRU Cache?
题型:综合开放题 难度:🔵 架构 岗位层级:架构师 面试知识域:计算机科学 标签:LRU、缓存、Map、算法、前端 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请说明 LRU Cache 的原理,并给出前端实现。
参考答案: LRU(Least Recently Used)缓存:
- 最近最少使用淘汰策略。
- 容量满时淘汰最久未访问的数据。
实现思路:
- 使用 Map 维护键值对,利用 Map 按插入顺序迭代的特性。
- get 时先删除再重新 set,使其变为最新。
- put 时若存在则更新,若超过容量则删除最老的(Map 第一个)。
示例:
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map();
}
get(key) {
if (!this.cache.has(key)) return -1;
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
put(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key);
} else if (this.cache.size >= this.capacity) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, value);
}
}复杂度:
- get 和 put 都是 O(1)。
应用场景:
- 图片缓存、API 响应缓存、路由缓存。
注意:
- Map 的 keys() 顺序即访问顺序。
- 也可用 Object + 双向链表实现。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
LRU 是最近最少使用淘汰。前端可用 Map 实现,get 时删除再 set 使其最新,put 时超容量删除 Map 第一个。get/put 都是 O(1)。
FB-53-CP-R-004:什么是虚拟 DOM?它的优缺点是什么?
题型:综合开放题 难度:🔵 架构 岗位层级:架构师 面试知识域:计算机科学 标签:虚拟 DOM、Virtual DOM、Diff、React 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请解释虚拟 DOM 的概念及其优缺点。
参考答案: 虚拟 DOM:
- 是对真实 DOM 的轻量 JavaScript 对象表示。
- 描述 UI 结构和属性。
- 框架通过比较新旧虚拟 DOM(Diff),最小化真实 DOM 操作。
工作流程:
- 状态变化生成新虚拟 DOM。
- 与旧虚拟 DOM Diff。
- 计算出最小变更集(patch)。
- 批量更新真实 DOM。
优点:
- 跨平台(虚拟 DOM 可映射到不同渲染目标)。
- 减少直接操作 DOM 的复杂度。
- 批量更新提升性能。
- 便于实现声明式 UI。
缺点:
- 额外的内存开销。
- Diff 计算本身有成本。
- 简单更新可能不如直接操作 DOM 快。
- 大型列表/复杂场景仍需优化(key、shouldComponentUpdate、memo)。
对比:
- 虚拟 DOM:React、Vue。
- 编译时优化:Svelte(无虚拟 DOM)。
- 脏检查:Angular。
注意:
- 虚拟 DOM 不是银弹,框架会针对不同场景优化。
- 现代框架趋向编译时优化减少运行时开销。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
虚拟 DOM 是真实 DOM 的 JS 对象表示,通过 Diff 最小化真实 DOM 更新。优点跨平台、减少直接 DOM 操作、批量更新;缺点有内存和 Diff 开销。React/Vue 用虚拟 DOM,Svelte 不用。
FB-53-CP-R-005:前端如何实现大文件分片上传?
题型:综合开放题 难度:🔵 架构 岗位层级:架构师 面试知识域:计算机科学 标签:大文件、分片上传、断点续传、前端 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请说明前端实现大文件分片上传和断点续传的方案。
参考答案: 大文件分片上传方案:
文件分片
jsconst chunkSize = 1024 * 1024; // 1MB const chunks = []; for (let i = 0; i < file.size; i += chunkSize) { chunks.push(file.slice(i, i + chunkSize)); }并发上传
- 控制并发数,避免占用过多连接。
- 使用 Promise 池或 async-pool。
断点续传
- 上传前向服务端查询已上传分片。
- 只上传未上传的分片。
校验
- 每个分片计算 MD5 或 hash。
- 服务端校验完整性。
进度显示
- 统计已上传字节数。
- 实时更新进度条。
合并请求
- 所有分片上传完成后,通知服务端合并。
取消/暂停
- 使用 AbortController 取消上传。
示例核心逻辑:
async function uploadFile(file) {
const chunks = createChunks(file);
const uploaded = await getUploadedChunks(file.hash);
for (let i = 0; i < chunks.length; i++) {
if (uploaded.includes(i)) continue;
await uploadChunk(chunks[i], i, file.hash);
}
await mergeChunks(file.hash, chunks.length);
}注意:
- 大文件 hash 计算耗时,可抽样计算。
- 网络波动要有重试机制。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
大文件上传用 Blob.slice 分片,控制并发,查询已上传分片实现断点续传,分片 hash 校验,实时进度,完成后合并。用 AbortController 取消。
FB-53-CP-R-006:如何设计一个前端路由系统?
题型:综合开放题 难度:🔵 架构 岗位层级:架构师 面试知识域:计算机科学 标签:前端路由、Hash、History API、SPA 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请说明前端路由的实现原理及 Hash 和 History 两种模式的区别。
参考答案: 前端路由实现原理:
监听 URL 变化
- Hash 模式:监听
hashchange事件。 - History 模式:监听
popstate事件。
- Hash 模式:监听
解析路径
- 根据 URL 路径匹配路由配置。
渲染对应组件
- 找到匹配的组件并渲染到指定容器。
Hash 模式:
- URL 中
#后面的部分。 - 不会触发页面刷新。
- 兼容性好,包括老 IE。
- URL 不够美观。
History 模式:
- 使用 HTML5 History API(pushState/replaceState)。
- URL 更自然,无
#。 - 需要服务端配置,防止刷新 404。
示例:
window.addEventListener('hashchange', () => {
render(location.hash.slice(1));
});
window.addEventListener('popstate', () => {
render(location.pathname);
});路由系统还要支持:
- 嵌套路由、动态路由、路由守卫、懒加载、404 处理。
注意:
- History 模式服务端必须返回 index.html。
- Hash 模式不利于 SEO。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
前端路由监听 URL 变化,解析路径渲染组件。Hash 模式监听 hashchange,兼容好但 URL 有 #;History 模式用 pushState,URL 美观但需服务端配置。
FB-53-CP-R-007:如何实现一个 Promise.all?
题型:综合开放题 难度:🔵 架构 岗位层级:架构师 面试知识域:计算机科学 标签:Promise、Promise.all、手写实现、异步 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请手写实现一个类似 Promise.all 的函数。
参考答案: Promise.all 实现:
function myPromiseAll(iterable) {
return new Promise((resolve, reject) => {
const results = [];
let count = 0;
const total = iterable.length;
if (total === 0) {
resolve(results);
return;
}
iterable.forEach((item, index) => {
Promise.resolve(item).then(
value => {
results[index] = value;
count++;
if (count === total) {
resolve(results);
}
},
reason => {
reject(reason);
}
);
});
});
}关键点:
- 所有 promise 并行执行。
- 结果按原顺序返回。
- 任一失败立即 reject。
- 输入可包含非 promise 值,用 Promise.resolve 包装。
Promise.allSettled 区别:
- 等待所有 promise 完成,无论成功失败。
- 返回每个 promise 的状态和结果。
Promise.race:
- 返回最先完成(无论成功失败)的 promise。
应用场景:
- 并行发起多个独立请求,等待全部完成。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
Promise.all 并行执行所有 promise,结果按顺序返回,任一失败 reject。实现时用 Promise.resolve 包装每个 item,维护 count 和 results 数组。
FB-53-SD-R-007:设计一个前端缓存策略系统。
题型:系统设计题 难度:🔵 架构 岗位层级:架构师 面试知识域:计算机科学 标签:缓存、策略、LRU、前端、设计 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请设计一个前端缓存系统,支持不同缓存策略。
参考答案: 前端缓存系统设计:
缓存层级
- Memory Cache:内存,最快但页面关闭丢失。
- Storage Cache:localStorage、IndexedDB、sessionStorage。
- HTTP Cache:浏览器网络缓存。
- Service Worker Cache:离线缓存。
缓存策略
- Cache First:优先缓存,无缓存再网络。
- Network First:优先网络,失败用缓存。
- Stale While Revalidate:先用缓存,同时后台更新。
- Cache Only:只用缓存。
- Network Only:只用网络。
过期机制
- TTL(Time To Live)。
- LRU/LFU 淘汰。
数据一致性
- 版本号控制。
- 写操作失效缓存。
接口设计
jscache.get(key); cache.set(key, value, { ttl: 60000, strategy: 'memory' }); cache.remove(key); cache.clear();错误处理
- 缓存读写失败降级到网络或默认行为。
监控
- 缓存命中率、过期率。
示例场景:
- API 响应用 Memory + IndexedDB 二级缓存。
- 静态资源用 Service Worker Cache。
- 用户配置用 localStorage。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
前端缓存系统分 memory、storage、HTTP、SW 层级,支持 cache first、network first、stale-while-revalidate 等策略,有过期机制和一致性控制,提供统一 API。
FB-53-SD-R-008:前端如何实现一个简单的前端框架(类 React/Vue)?
题型:系统设计题 难度:🔵 架构 岗位层级:架构师 面试知识域:计算机科学 标签:前端框架、响应式、VDOM、设计 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请设计一个最简前端框架的核心机制。
参考答案: 最简前端框架核心:
响应式系统
- 使用 Proxy 或 defineProperty 监听数据变化。
- 数据变化时通知依赖更新。
模板编译/渲染函数
- 将模板编译为渲染函数。
- 渲染函数返回虚拟 DOM。
虚拟 DOM 与 Diff
- 用 JS 对象表示 DOM。
- 比较新旧虚拟 DOM,生成 patch。
DOM 更新
- 根据 patch 最小化更新真实 DOM。
生命周期
- mounted、updated、destroyed。
事件绑定
- 在虚拟 DOM 层面绑定事件,委托到真实 DOM。
组件系统
- 支持组件定义、props、事件通信。
最简实现思路:
// 响应式
const state = reactive({ count: 0 });
// 渲染
function render() {
return h('div', {}, [state.count]);
}
// 更新
effect(() => {
patch(oldVNode, render());
});挑战:
- 完整框架还需处理 keyed diff、异步更新、组件嵌套、插槽、Teleport 等。
- 但作为理解核心原理已足够。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
最简前端框架核心:响应式系统监听数据变化,模板编译为渲染函数生成 VDOM,Diff 生成 patch,更新真实 DOM,加生命周期、事件、组件系统。
FB-53-CO-B-015:什么是递归?递归和迭代的区别是什么?
题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:递归、迭代、算法 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请解释递归的概念,并说明递归和迭代的区别。
参考答案: 递归:
- 函数直接或间接调用自身。
- 必须有终止条件(base case),否则无限递归。
- 适合解决具有重复子结构的问题。
示例:
function factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}迭代:
- 使用循环重复执行代码块。
- 通常更节省内存,因为没有调用栈开销。
区别:
| 特性 | 递归 | 迭代 |
|---|---|---|
| 实现 | 函数自调用 | 循环 |
| 可读性 | 代码简洁,思路自然 | 有时更冗长 |
| 性能 | 有栈开销,可能栈溢出 | 通常更高效 |
| 适用 | 树、图、分治 | 线性遍历 |
注意:
- 递归过深会导致栈溢出。
- 尾递归在某些引擎可优化,但 JS 引擎支持不一。
- 递归可转换为迭代,常用栈模拟。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
递归是函数调用自身,要有终止条件。迭代是循环。递归代码简洁但可能有栈溢出,迭代通常更高效。树、图、分治适合递归,线性遍历适合迭代。
FB-53-CO-B-016:什么是二分查找?时间复杂度是多少?
题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:二分查找、算法、时间复杂度 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请解释二分查找的原理和时间复杂度。
参考答案: 二分查找:
- 在有序数组中查找目标值。
- 每次比较中间元素,将搜索范围缩小一半。
步骤:
- 确定左右边界 left、right。
- 计算中间 mid = Math.floor((left + right) / 2)。
- 比较 target 与 arr[mid]。
- 相等:返回 mid。
- target < arr[mid]:right = mid - 1。
- target > arr[mid]:left = mid + 1。
- 重复直到找到或 left > right。
时间复杂度:O(log n) 空间复杂度:O(1) 迭代版,O(log n) 递归版。
示例:
function binarySearch(arr, target) {
let left = 0, right = arr.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (arr[mid] === target) return mid;
if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1;
}注意:
- 数组必须有序。
- 注意边界条件,避免死循环。
- 可用于查找第一个/最后一个满足条件的元素。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
二分查找在有序数组中每次缩小一半范围,时间 O(log n)。注意数组必须有序,边界条件要写对。
FB-53-CO-A-013:什么是动态规划(DP)?请举一个前端中的例子。
题型:概念题 难度:🟡 进阶 岗位层级:高级 面试知识域:计算机科学 标签:动态规划、DP、算法、前端 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请解释动态规划的思想,并给出前端应用示例。
参考答案: 动态规划:
- 将复杂问题分解为子问题。
- 保存子问题结果,避免重复计算。
- 适用于最优子结构和重叠子问题。
核心思想:
- 状态定义:dp[i] 表示什么。
- 状态转移:dp[i] 如何从 dp[i-1] 等推导。
- 初始条件:dp[0] 等。
- 返回值:最终答案。
前端示例:
最长公共子序列(LCS)
- 对比两段文本差异(diff 算法)。
斐波那契数列
- 缓存中间结果。
背包问题
- 资源分配、预算优化。
编辑距离
- 自动补全、拼写检查。
React 的 diff 算法
- 虽然不完全等同于经典 DP,但用了类似的子问题复用思想。
示例:斐波那契
function fib(n) {
if (n <= 1) return n;
const dp = [0, 1];
for (let i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}注意:
- DP 可以用滚动数组优化空间。
- 不是所有问题都适合 DP。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
动态规划把问题分解为子问题并缓存结果。前端可用于 diff、自动补全、编辑距离等。核心是状态定义、状态转移、初始条件。
FB-53-CO-A-014:什么是 BFS 和 DFS?
题型:概念题 难度:🟡 进阶 岗位层级:高级 面试知识域:计算机科学 标签:BFS、DFS、图、树、遍历 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请解释 BFS 和 DFS 的区别及适用场景。
参考答案: BFS(广度优先搜索):
- 先访问当前节点的所有邻居,再访问邻居的邻居。
- 使用队列实现。
- 适合找最短路径(无权图)。
DFS(深度优先搜索):
- 沿着一条路径走到尽头,再回溯。
- 使用栈(递归或显式栈)实现。
- 适合连通性检测、拓扑排序、全排列。
对比:
| 特性 | BFS | DFS |
|---|---|---|
| 数据结构 | 队列 | 栈/递归 |
| 空间 | 较宽时大 | 较深时大 |
| 最短路径 | 无权图可找到 | 不一定 |
| 实现 | 迭代 | 递归或迭代 |
前端应用:
- DOM 树遍历:BFS 找层级,DFS 找子孙。
- 依赖分析:DFS 检测循环依赖。
- 路由匹配:DFS 遍历路由树。
示例:
function bfs(root) {
const queue = [root];
while (queue.length) {
const node = queue.shift();
console.log(node.value);
queue.push(...node.children);
}
}注意:
- 图遍历要记录 visited,避免循环。
- 递归 DFS 注意栈深度。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
BFS 用队列一层层访问,适合最短路径;DFS 用栈一条路走到黑再回溯,适合连通性、拓扑排序。前端用于 DOM 遍历、依赖分析、路由匹配。
FB-53-CP-A-001:前端如何实现一个 Trie 树(前缀树)?
题型:综合开放题 难度:🟡 进阶 岗位层级:高级 面试知识域:计算机科学 标签:Trie、前缀树、自动补全、前端 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请说明 Trie 树的原理及前端应用场景。
参考答案: Trie 树:
- 用于高效存储和查找字符串集合。
- 每个节点代表一个字符,从根到叶子的路径构成一个字符串。
- 查找、插入时间复杂度 O(L),L 为字符串长度。
前端应用:
- 自动补全/搜索建议。
- 前缀匹配。
- 拼写检查。
- IP 路由最长前缀匹配。
实现:
class TrieNode {
constructor() {
this.children = {};
this.isEnd = false;
}
}
class Trie {
constructor() {
this.root = new TrieNode();
}
insert(word) {
let node = this.root;
for (const ch of word) {
if (!node.children[ch]) node.children[ch] = new TrieNode();
node = node.children[ch];
}
node.isEnd = true;
}
search(word) {
let node = this.root;
for (const ch of word) {
if (!node.children[ch]) return false;
node = node.children[ch];
}
return node.isEnd;
}
startsWith(prefix) {
let node = this.root;
for (const ch of prefix) {
if (!node.children[ch]) return false;
node = node.children[ch];
}
return true;
}
}优化:
- 压缩 Trie(Radix Tree)减少节点数。
- 双数组 Trie 节省内存。
注意:
- Trie 空间换时间。
- 字符集大时空间开销高。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
Trie 树是按字符组织的树,用于高效字符串查找。前端用于自动补全、前缀匹配。插入查找都是 O(L)。可用压缩 Trie 优化空间。
FB-53-CO-A-015:解释一下 HTTP 缓存机制。
题型:概念题 难度:🟡 进阶 岗位层级:高级 面试知识域:计算机科学 标签:HTTP、缓存、Cache-Control、ETag 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请说明 HTTP 缓存的相关头部和机制。
参考答案: HTTP 缓存:
强缓存
- 浏览器直接从本地缓存读取,不发请求。
- 响应头:
Cache-Control: max-age=3600(秒)Expires(过期时间,已较少用)
协商缓存
- 缓存过期后,浏览器向服务器确认是否可用。
- 响应头:
Last-Modified+ 请求头If-Modified-SinceETag+ 请求头If-None-Match
- 服务器返回 304 表示缓存可用。
Cache-Control 常用值
no-cache:每次协商缓存。no-store:不缓存。private:仅客户端缓存。public:可被中间代理缓存。max-age:缓存最大时间。
前端应用
- 静态资源加 hash 文件名,配合
max-age=31536000。 - HTML 文件不缓存或短缓存。
- API 响应根据业务设置缓存策略。
- 静态资源加 hash 文件名,配合
缓存位置
- Service Worker、Memory Cache、Disk Cache、Push Cache。
注意:
- 强缓存和协商缓存可配合使用。
- 更新资源时改文件名或版本号。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
HTTP 缓存分强缓存和协商缓存。强缓存用 Cache-Control max-age,协商缓存用 Last-Modified/ETag。前端静态资源加 hash 长缓存,HTML 短缓存。
FB-53-CO-B-017:什么是进程和线程?前端中如何理解?
题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:进程、线程、浏览器、并发 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请解释进程和线程的区别,以及浏览器中的进程模型。
参考答案: 进程(Process):
- 操作系统资源分配的基本单位。
- 拥有独立的内存空间。
- 进程间通信需要 IPC。
线程(Thread):
- CPU 调度的基本单位。
- 同一进程内的线程共享内存。
- 线程切换开销小于进程。
浏览器进程模型:
多进程架构
- 浏览器主进程、GPU 进程、渲染进程、插件进程、网络进程等。
- 每个标签页通常是独立渲染进程(站点隔离后可能更细)。
渲染进程
- 包含主线程、合成线程、IO 线程、工作线程等。
- 主线程执行 JS、样式计算、布局、绘制。
Web Worker
- 在独立线程运行 JS,不阻塞主线程。
- 与主线程通过 postMessage 通信。
Service Worker
- 独立线程,可拦截网络请求、缓存资源。
前端意义:
- 理解浏览器多进程有助于排查性能和安全问题。
- 利用 Worker 避免主线程阻塞。
注意:
- JS 单线程指的是主线程单线程。
- Worker 不能访问 DOM。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
进程是资源分配单位,线程是调度单位。浏览器是多进程架构,每个标签页独立渲染进程。主线程单线程,Worker 在独立线程。
FB-53-CO-B-018:解释一下浏览器的事件委托(Event Delegation)。
题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:事件委托、冒泡、性能、前端 出现频率:高频 预计回答时长:5-8 分钟
题目描述: 请说明事件委托的原理和优势。
参考答案: 事件委托:
- 利用事件冒泡机制,将事件监听器绑定到父元素上。
- 通过 event.target 判断实际触发事件的子元素。
优势:
减少内存占用
- 不需要给每个子元素绑定事件。
- 特别适合大量子元素(如列表)。
动态元素支持
- 新增子元素无需重新绑定事件。
代码简洁
- 统一管理事件处理逻辑。
示例:
ul.addEventListener('click', (e) => {
if (e.target.tagName === 'LI') {
console.log(e.target.textContent);
}
});注意:
- 不冒泡的事件(如 focus、blur)不能委托。
- 需要正确判断 target,避免误触发。
- 复杂交互可能需要 stopPropagation 配合。
适用场景:
- 长列表、表格、动态菜单。
- 大量相似元素需要相同事件处理。
评分维度:
- 能准确理解问题并给出结构化回答(40%)
- 能结合实际案例或数据说明(30%)
- 能体现业务思维与技术落地的结合(30%)
常见错误:
- 回答过于空泛,缺乏具体做法。
- 只谈技术实现,忽略业务目标和约束。
- 没有考虑风险和可执行性。
口头回答版:
事件委托把监听器绑到父元素,利用冒泡通过 event.target 判断子元素。优点是减少内存、支持动态元素、代码简洁。不冒泡的事件不能委托。