Skip to content

计算机基础面试题

本题库共收录 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 表示法。

分析方法:

  1. 找出基本操作

    • 循环体、递归调用、比较操作等。
  2. 统计执行次数

    • 单层循环:O(n)。
    • 双层嵌套循环:O(n²)。
    • 二分查找:O(log n)。
  3. 忽略低阶项和常数

    • O(2n + 100) = O(n)。
    • O(n² + n) = O(n²)。
  4. 空间分析

    • 变量、数组、递归栈、哈希表等。

常见复杂度:

复杂度名称示例
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 遍历,说明实现方式、时间复杂度和应用场景。

参考答案

维度BFSDFS
数据结构队列栈(递归或显式栈)
遍历顺序按层扩展一条路走到黑再回溯
空间复杂度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 全局最优,会考虑所有选择。

解题步骤:

  1. 定义状态。
  2. 找状态转移方程。
  3. 初始化边界。
  4. 确定遍历顺序。
  5. 可选空间优化。

常见题型:

  • 背包、最长公共子序列、最长递增子序列、编辑距离、股票问题。

评分维度

  • 核心思想(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 的特性,并说明前端场景中的应用。

参考答案

维度TCPUDP
连接面向连接无连接
可靠性可靠,有序,重传不可靠,无序
流量控制
拥塞控制
头部开销
传输效率相对较低
适用文件、网页、邮件音视频、实时游戏、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 分钟

题目描述: 请说明哈希表的工作原理及常见冲突解决方法。

参考答案: 哈希表原理:

  1. 哈希函数

    • 将 key 映射为数组下标。
    • 好的哈希函数应均匀分布、计算快。
  2. 存储

    • 根据哈希值将数据存入对应桶。
  3. 查找

    • 计算 key 的哈希值,直接定位桶。
    • 理想情况 O(1)。

冲突(Collision):

  • 不同 key 映射到同一位置。

解决方法:

  1. 拉链法(Separate Chaining)

    • 每个桶维护一个链表或其他结构。
    • 冲突元素加入链表。
  2. 开放寻址法(Open Addressing)

    • 冲突时按某种探测策略找下一个空桶。
    • 线性探测、二次探测、双重哈希。
  3. 再哈希(Rehashing)

    • 冲突严重时扩容并重新计算哈希。
  4. 公共溢出区

    • 冲突元素放到单独区域。

注意:

  • 负载因子(元素数/桶数)影响性能。
  • 负载因子过高时需扩容。
  • JS 的 Object/Map 底层使用哈希表。

评分维度

  • 能准确理解问题并给出结构化回答(40%)
  • 能结合实际案例或数据说明(30%)
  • 能体现业务思维与技术落地的结合(30%)

常见错误

  • 回答过于空泛,缺乏具体做法。
  • 只谈技术实现,忽略业务目标和约束。
  • 没有考虑风险和可执行性。

口头回答版

哈希表用哈希函数把 key 映射为下标,理想 O(1)。冲突可用拉链法、开放寻址法、再哈希。负载因子高时要扩容。


FB-53-CO-A-012:什么是二叉树、BST、AVL 树、红黑树?

题型:概念题 难度:🟡 进阶 岗位层级:高级 面试知识域:计算机科学 标签:二叉树、BST、AVL、红黑树、数据结构 出现频率:高频 预计回答时长:5-8 分钟

题目描述: 请说明二叉树、二叉搜索树、AVL 树、红黑树的概念和区别。

参考答案: 概念:

  1. 二叉树(Binary Tree)

    • 每个节点最多两个子节点。
    • 常见遍历:前序、中序、后序、层序。
  2. 二叉搜索树(BST)

    • 左子树所有节点 < 根节点 < 右子树所有节点。
    • 查找、插入、删除平均 O(log n),最坏 O(n)。
  3. AVL 树

    • 自平衡 BST。
    • 任意节点左右子树高度差不超过 1。
    • 查找快,但旋转操作多,插入删除较慢。
  4. 红黑树

    • 近似平衡 BST。
    • 通过五条颜色规则保持平衡。
    • 插入删除旋转少,综合性能好。
    • Java HashMap、C++ map、Linux 内核大量使用。

对比:

特性BSTAVL红黑树
平衡性不一定严格近似
查找平均 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 分钟

题目描述: 请说明深拷贝和浅拷贝的区别,以及前端实现深拷贝的方法。

参考答案: 浅拷贝:

  • 只复制对象的第一层属性。
  • 嵌套对象仍然共享引用。
  • 修改副本的嵌套对象会影响原对象。

深拷贝:

  • 递归复制所有层级。
  • 副本和原对象完全独立。

前端实现方式:

  1. JSON 方法

    js
    const copy = JSON.parse(JSON.stringify(obj));
    • 简单但无法处理函数、undefined、Date、RegExp、Map、Set、循环引用。
  2. 递归实现

    js
    function 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;
    }
  3. structuredClone

    • 浏览器原生 API。
    • 支持更多类型,但不支持函数。
  4. lodash.cloneDeep

    • 成熟库,处理各种边界情况。

选择:

  • 简单对象:JSON 或 structuredClone。
  • 复杂对象:递归实现或 lodash。

评分维度

  • 能准确理解问题并给出结构化回答(40%)
  • 能结合实际案例或数据说明(30%)
  • 能体现业务思维与技术落地的结合(30%)

常见错误

  • 回答过于空泛,缺乏具体做法。
  • 只谈技术实现,忽略业务目标和约束。
  • 没有考虑风险和可执行性。

口头回答版

浅拷贝只复制第一层,嵌套共享引用;深拷贝递归复制完全独立。前端可用 JSON.parse/stringify、递归、structuredClone、lodash.cloneDeep。


FB-53-CO-B-011:什么是闭包?有什么应用和注意事项?

题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:闭包、JavaScript、作用域、内存 出现频率:高频 预计回答时长:5-8 分钟

题目描述: 请解释闭包的概念,并说明其应用场景和注意事项。

参考答案: 闭包:

  • 函数能够记住并访问其词法作用域,即使函数在其词法作用域之外执行。
  • 闭包 = 函数 + 引用环境。

示例:

js
function createCounter() {
  let count = 0;
  return function() {
    return ++count;
  };
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2

应用场景:

  1. 数据封装/私有变量

    • 模拟类和私有属性。
  2. 函数工厂

    • 创建配置化函数。
  3. 回调和异步

    • 保持对创建时状态的引用。
  4. 柯里化

    • 多参数函数转换为单参数链式调用。
  5. 防抖节流

    • 保持计时器状态。

注意事项:

  • 内存泄漏:闭包持有不再需要的引用。
  • 循环中的闭包:注意变量共享问题(用 let 或 IIFE)。
  • 调试困难:过多闭包使作用域链复杂。

最佳实践:

  • 只在需要时使用闭包。
  • 避免意外持有大对象。

评分维度

  • 能准确理解问题并给出结构化回答(40%)
  • 能结合实际案例或数据说明(30%)
  • 能体现业务思维与技术落地的结合(30%)

常见错误

  • 回答过于空泛,缺乏具体做法。
  • 只谈技术实现,忽略业务目标和约束。
  • 没有考虑风险和可执行性。

口头回答版

闭包是函数记住并访问其词法作用域的能力。用于数据封装、函数工厂、回调、柯里化、防抖节流。注意内存泄漏和循环中的变量共享。


FB-53-CO-B-012:什么是事件循环(Event Loop)?宏任务和微任务有什么区别?

题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:事件循环、Event Loop、宏任务、微任务、JavaScript 出现频率:高频 预计回答时长:5-8 分钟

题目描述: 请解释 JavaScript 的事件循环机制,以及宏任务和微任务的区别。

参考答案: 事件循环:

  • JavaScript 是单线程语言,通过事件循环实现异步非阻塞。
  • 事件循环不断检查调用栈和任务队列,将任务放入调用栈执行。

任务类型:

  1. 同步任务

    • 直接放入调用栈执行。
  2. 宏任务(Macrotask)

    • setTimeout、setInterval、setImmediate(Node)、I/O、UI 渲染。
    • 每个事件循环周期执行一个宏任务。
  3. 微任务(Microtask)

    • Promise.then/catch/finally、MutationObserver、queueMicrotask。
    • 当前宏任务执行完后,立即执行所有微任务。

执行顺序:

  1. 执行同步代码。
  2. 执行所有微任务。
  3. 执行一个宏任务。
  4. 重复 2-3。

示例:

js
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

继承方式:

  1. 原型链继承

    js
    Child.prototype = new Parent();
    • 缺点:共享引用类型属性。
  2. 构造函数继承

    js
    function Child() { Parent.call(this); }
    • 缺点:无法继承原型方法。
  3. 组合继承

    • 构造函数继承 + 原型链继承。
  4. 寄生组合继承

    • 最优方案:用 Object.create 连接原型。
  5. ES6 Class

    js
    class 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、按钮点击防重复。

对比:

特性DebounceThrottle
触发方式停止触发后执行按固定频率执行
执行次数可能一次多次
场景输入搜索滚动监听

实现:

js
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 第一个)。

示例:

js
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 操作。

工作流程:

  1. 状态变化生成新虚拟 DOM。
  2. 与旧虚拟 DOM Diff。
  3. 计算出最小变更集(patch)。
  4. 批量更新真实 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 分钟

题目描述: 请说明前端实现大文件分片上传和断点续传的方案。

参考答案: 大文件分片上传方案:

  1. 文件分片

    js
    const chunkSize = 1024 * 1024; // 1MB
    const chunks = [];
    for (let i = 0; i < file.size; i += chunkSize) {
      chunks.push(file.slice(i, i + chunkSize));
    }
  2. 并发上传

    • 控制并发数,避免占用过多连接。
    • 使用 Promise 池或 async-pool。
  3. 断点续传

    • 上传前向服务端查询已上传分片。
    • 只上传未上传的分片。
  4. 校验

    • 每个分片计算 MD5 或 hash。
    • 服务端校验完整性。
  5. 进度显示

    • 统计已上传字节数。
    • 实时更新进度条。
  6. 合并请求

    • 所有分片上传完成后,通知服务端合并。
  7. 取消/暂停

    • 使用 AbortController 取消上传。

示例核心逻辑:

js
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 两种模式的区别。

参考答案: 前端路由实现原理:

  1. 监听 URL 变化

    • Hash 模式:监听 hashchange 事件。
    • History 模式:监听 popstate 事件。
  2. 解析路径

    • 根据 URL 路径匹配路由配置。
  3. 渲染对应组件

    • 找到匹配的组件并渲染到指定容器。

Hash 模式:

  • URL 中 # 后面的部分。
  • 不会触发页面刷新。
  • 兼容性好,包括老 IE。
  • URL 不够美观。

History 模式:

  • 使用 HTML5 History API(pushState/replaceState)。
  • URL 更自然,无 #
  • 需要服务端配置,防止刷新 404。

示例:

js
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 实现:

js
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 分钟

题目描述: 请设计一个前端缓存系统,支持不同缓存策略。

参考答案: 前端缓存系统设计:

  1. 缓存层级

    • Memory Cache:内存,最快但页面关闭丢失。
    • Storage Cache:localStorage、IndexedDB、sessionStorage。
    • HTTP Cache:浏览器网络缓存。
    • Service Worker Cache:离线缓存。
  2. 缓存策略

    • Cache First:优先缓存,无缓存再网络。
    • Network First:优先网络,失败用缓存。
    • Stale While Revalidate:先用缓存,同时后台更新。
    • Cache Only:只用缓存。
    • Network Only:只用网络。
  3. 过期机制

    • TTL(Time To Live)。
    • LRU/LFU 淘汰。
  4. 数据一致性

    • 版本号控制。
    • 写操作失效缓存。
  5. 接口设计

    js
    cache.get(key);
    cache.set(key, value, { ttl: 60000, strategy: 'memory' });
    cache.remove(key);
    cache.clear();
  6. 错误处理

    • 缓存读写失败降级到网络或默认行为。
  7. 监控

    • 缓存命中率、过期率。

示例场景:

  • 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 分钟

题目描述: 请设计一个最简前端框架的核心机制。

参考答案: 最简前端框架核心:

  1. 响应式系统

    • 使用 Proxy 或 defineProperty 监听数据变化。
    • 数据变化时通知依赖更新。
  2. 模板编译/渲染函数

    • 将模板编译为渲染函数。
    • 渲染函数返回虚拟 DOM。
  3. 虚拟 DOM 与 Diff

    • 用 JS 对象表示 DOM。
    • 比较新旧虚拟 DOM,生成 patch。
  4. DOM 更新

    • 根据 patch 最小化更新真实 DOM。
  5. 生命周期

    • mounted、updated、destroyed。
  6. 事件绑定

    • 在虚拟 DOM 层面绑定事件,委托到真实 DOM。
  7. 组件系统

    • 支持组件定义、props、事件通信。

最简实现思路:

js
// 响应式
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),否则无限递归。
  • 适合解决具有重复子结构的问题。

示例:

js
function factorial(n) {
  if (n <= 1) return 1;
  return n * factorial(n - 1);
}

迭代:

  • 使用循环重复执行代码块。
  • 通常更节省内存,因为没有调用栈开销。

区别:

特性递归迭代
实现函数自调用循环
可读性代码简洁,思路自然有时更冗长
性能有栈开销,可能栈溢出通常更高效
适用树、图、分治线性遍历

注意:

  • 递归过深会导致栈溢出。
  • 尾递归在某些引擎可优化,但 JS 引擎支持不一。
  • 递归可转换为迭代,常用栈模拟。

评分维度

  • 能准确理解问题并给出结构化回答(40%)
  • 能结合实际案例或数据说明(30%)
  • 能体现业务思维与技术落地的结合(30%)

常见错误

  • 回答过于空泛,缺乏具体做法。
  • 只谈技术实现,忽略业务目标和约束。
  • 没有考虑风险和可执行性。

口头回答版

递归是函数调用自身,要有终止条件。迭代是循环。递归代码简洁但可能有栈溢出,迭代通常更高效。树、图、分治适合递归,线性遍历适合迭代。


FB-53-CO-B-016:什么是二分查找?时间复杂度是多少?

题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:二分查找、算法、时间复杂度 出现频率:高频 预计回答时长:5-8 分钟

题目描述: 请解释二分查找的原理和时间复杂度。

参考答案: 二分查找:

  • 在有序数组中查找目标值。
  • 每次比较中间元素,将搜索范围缩小一半。

步骤:

  1. 确定左右边界 left、right。
  2. 计算中间 mid = Math.floor((left + right) / 2)。
  3. 比较 target 与 arr[mid]。
    • 相等:返回 mid。
    • target < arr[mid]:right = mid - 1。
    • target > arr[mid]:left = mid + 1。
  4. 重复直到找到或 left > right。

时间复杂度:O(log n) 空间复杂度:O(1) 迭代版,O(log n) 递归版。

示例:

js
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 分钟

题目描述: 请解释动态规划的思想,并给出前端应用示例。

参考答案: 动态规划:

  • 将复杂问题分解为子问题。
  • 保存子问题结果,避免重复计算。
  • 适用于最优子结构和重叠子问题。

核心思想:

  1. 状态定义:dp[i] 表示什么。
  2. 状态转移:dp[i] 如何从 dp[i-1] 等推导。
  3. 初始条件:dp[0] 等。
  4. 返回值:最终答案。

前端示例:

  1. 最长公共子序列(LCS)

    • 对比两段文本差异(diff 算法)。
  2. 斐波那契数列

    • 缓存中间结果。
  3. 背包问题

    • 资源分配、预算优化。
  4. 编辑距离

    • 自动补全、拼写检查。
  5. React 的 diff 算法

    • 虽然不完全等同于经典 DP,但用了类似的子问题复用思想。

示例:斐波那契

js
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(深度优先搜索):

  • 沿着一条路径走到尽头,再回溯。
  • 使用栈(递归或显式栈)实现。
  • 适合连通性检测、拓扑排序、全排列。

对比:

特性BFSDFS
数据结构队列栈/递归
空间较宽时大较深时大
最短路径无权图可找到不一定
实现迭代递归或迭代

前端应用:

  • DOM 树遍历:BFS 找层级,DFS 找子孙。
  • 依赖分析:DFS 检测循环依赖。
  • 路由匹配:DFS 遍历路由树。

示例:

js
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 路由最长前缀匹配。

实现:

js
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 缓存:

  1. 强缓存

    • 浏览器直接从本地缓存读取,不发请求。
    • 响应头:
      • Cache-Control: max-age=3600(秒)
      • Expires(过期时间,已较少用)
  2. 协商缓存

    • 缓存过期后,浏览器向服务器确认是否可用。
    • 响应头:
      • Last-Modified + 请求头 If-Modified-Since
      • ETag + 请求头 If-None-Match
    • 服务器返回 304 表示缓存可用。
  3. Cache-Control 常用值

    • no-cache:每次协商缓存。
    • no-store:不缓存。
    • private:仅客户端缓存。
    • public:可被中间代理缓存。
    • max-age:缓存最大时间。
  4. 前端应用

    • 静态资源加 hash 文件名,配合 max-age=31536000
    • HTML 文件不缓存或短缓存。
    • API 响应根据业务设置缓存策略。
  5. 缓存位置

    • 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 调度的基本单位。
  • 同一进程内的线程共享内存。
  • 线程切换开销小于进程。

浏览器进程模型:

  1. 多进程架构

    • 浏览器主进程、GPU 进程、渲染进程、插件进程、网络进程等。
    • 每个标签页通常是独立渲染进程(站点隔离后可能更细)。
  2. 渲染进程

    • 包含主线程、合成线程、IO 线程、工作线程等。
    • 主线程执行 JS、样式计算、布局、绘制。
  3. Web Worker

    • 在独立线程运行 JS,不阻塞主线程。
    • 与主线程通过 postMessage 通信。
  4. Service Worker

    • 独立线程,可拦截网络请求、缓存资源。

前端意义:

  • 理解浏览器多进程有助于排查性能和安全问题。
  • 利用 Worker 避免主线程阻塞。

注意:

  • JS 单线程指的是主线程单线程。
  • Worker 不能访问 DOM。

评分维度

  • 能准确理解问题并给出结构化回答(40%)
  • 能结合实际案例或数据说明(30%)
  • 能体现业务思维与技术落地的结合(30%)

常见错误

  • 回答过于空泛,缺乏具体做法。
  • 只谈技术实现,忽略业务目标和约束。
  • 没有考虑风险和可执行性。

口头回答版

进程是资源分配单位,线程是调度单位。浏览器是多进程架构,每个标签页独立渲染进程。主线程单线程,Worker 在独立线程。


FB-53-CO-B-018:解释一下浏览器的事件委托(Event Delegation)。

题型:概念题 难度:🟢 基础 岗位层级:初级 面试知识域:计算机科学 标签:事件委托、冒泡、性能、前端 出现频率:高频 预计回答时长:5-8 分钟

题目描述: 请说明事件委托的原理和优势。

参考答案: 事件委托:

  • 利用事件冒泡机制,将事件监听器绑定到父元素上。
  • 通过 event.target 判断实际触发事件的子元素。

优势:

  1. 减少内存占用

    • 不需要给每个子元素绑定事件。
    • 特别适合大量子元素(如列表)。
  2. 动态元素支持

    • 新增子元素无需重新绑定事件。
  3. 代码简洁

    • 统一管理事件处理逻辑。

示例:

js
ul.addEventListener('click', (e) => {
  if (e.target.tagName === 'LI') {
    console.log(e.target.textContent);
  }
});

注意:

  • 不冒泡的事件(如 focus、blur)不能委托。
  • 需要正确判断 target,避免误触发。
  • 复杂交互可能需要 stopPropagation 配合。

适用场景:

  • 长列表、表格、动态菜单。
  • 大量相似元素需要相同事件处理。

评分维度

  • 能准确理解问题并给出结构化回答(40%)
  • 能结合实际案例或数据说明(30%)
  • 能体现业务思维与技术落地的结合(30%)

常见错误

  • 回答过于空泛,缺乏具体做法。
  • 只谈技术实现,忽略业务目标和约束。
  • 没有考虑风险和可执行性。

口头回答版

事件委托把监听器绑到父元素,利用冒泡通过 event.target 判断子元素。优点是减少内存、支持动态元素、代码简洁。不冒泡的事件不能委托。


基于 MIT 协议发布