一个常见的场景
你做了三年 React 开发,项目经验不少,也看过不少源码解析文章。忽然决定要换工作,打开招聘网站扫了一圈 JD,发现每一条都像是专门针对自己的弱点写的:要懂工程化、要有架构设计能力、要了解前端底层、要能讲清楚技术选型。心里咯噔一下,觉得自己好像什么都没准备好。
这是大多数有几年经验的前端工程师在准备跳槽时都会遇到的状况。但这种"什么都没准备好"的感觉,通常不是因为知识真的不够,而是准备的方式出了问题。
为什么会觉得自己没准备好
一个三年经验的工程师,知识点实际上已经积累了不少。Promise、async/await、useEffect、Virtual DOM、浏览器缓存这些概念,在日常工作中都接触得到。问题是这些东西在脑子里是零散的,没有连成一张网。当面试官问"说说 React 的更新流程",你能模模糊糊答出"会触发 re-render,然后 diff",但答不细。问"useEffect 的依赖数组怎么决定",你知道"变了就重新跑",但说不清"为什么有时候会死循环"。
这种状态叫知识有,但不成体系。它带来的问题是:遇到新问题的时候,你没法快速把它挂到已有知识网上去;需要在面试里讲清楚一个机制的时候,你只能靠背,而没法用自己的理解推出来。
这和"没学过"不一样。"没学过"的人是知道自己不会的,可以从头学。而"学过但不成体系"的人往往更焦虑——因为不知道自己到底哪里有缺口。
另一个常见的准备方式
大多数人在这种情况下会做一件事:继续找材料。
收藏夹里又多了几篇"React 原理深入"的文章,硬盘里多了一套"前端工程化面试题",朋友圈里多了一堆分享链接。打开书单管理软件,书单越来越长,读完的永远是前几页。
这种准备方式有一个很形象的比喻:用补材料的速度来缓解对未知的焦虑。每次想到"自己可能不懂某个点",第一反应就是去找一篇讲那个点的文章,而不是先搞清楚"这个点在整体知识体系里处于什么位置"。
这样做的好处是焦虑会暂时降低。坏处是,材料越积越多,真正读进去的越来越少,知识越来越散,反而更觉得自己没准备好。
这不是意志力的问题,也不是材料不够的问题。这是准备方式的结构性问题。
面试真正在看什么
在讨论怎么准备之前,先要搞清楚面试到底在看什么。
对于中高级前端岗位,面试通常分三层在看:
第一层:能不能干活。这是基础线——会不会写代码,能不能独立完成一个功能,遇到问题能不能排查。校招和初阶社招主要看这一层。
第二层:理解有多深。到了三年以上,候选人的差距主要体现在这里。同样用了三年 React,有人只能说清楚"state 变了组件会重新渲染",有人能讲清楚"React 的更新是异步的,setState 在事件处理函数里会被合并,Fiber 架构把渲染分成了 render phase 和 commit phase,lane 模型决定了更新的优先级"。这两类人在实际项目里处理复杂交互的能力差距很大,面试官当然会想办法区分出来。
第三层:能不能讲清楚。这一层经常被忽略。有些人确实理解了,但讲出来一团糟——要么太啰嗦抓不住重点,要么只会背答案而不会举一反三。面试本质上是口头表达能力的考察,你脑子里有一张网,但表达不出来,面试官就看不见。
这三层并不是递进关系,而是同时考察的。一个高级岗位的面试,通常三轮技术面分别会侧重其中一层或两层。
为什么"继续搜材料"对第二层和第三层没用
对第一层来说,多刷题、多写代码确实有效。但对第二层和第三层,继续搜材料的效果很有限。
对第二层:网上大多数源码分析文章是"碎片式讲解"——单独讲 React Fiber,或者单独讲 useEffect,或者单独讲 Virtual DOM。每篇文章讲一个点,讲得不算浅,但它们之间没有连接。你读完十篇,理解了十个点,但这十个点在脑子里还是散的。你没法用自己的语言串起来,因为从来没有人教你怎么串。
对第三层:面试表达需要训练,不是靠看材料能解决的。你需要对着空气讲、在限定时间内把一个机制讲清楚、接受反馈、修改、再讲一遍。没有人这样练过,看到面试题的第一反应是"我好像看过这个",然后就开始紧张地回忆文章里怎么说的,而不是按自己的理解组织语言。
这就是为什么很多人觉得自己"看懂了但讲不出来"。不是记忆力的问题,是从来没有做过"把理解变成表达"的专项训练。
什么是"知识骨架"
知识骨架这个说法,听起来有点抽象,但它描述的状态其实很具体。
当一个人有知识骨架的时候,遇到了一个新问题会这样反应:
"这个问题我好像没遇到过,但是它应该属于 X 这个领域——X 是做 Y 的,它和 Z 之间有关系——所以这个问题大概可以从 Y 和 Z 的交叉点出发来想。"
而没有骨架的人会这样反应:
"这个问题我没看过,搜一下有没有相关文章……"
两者的差距不在于知识量,而在于有没有一张网,能不能快速把新问题挂到这张网上。
骨架是怎么建立的?不是靠一篇一篇地读文章,而是靠反复做"连接"这个动作。
每次学到一个新概念,主动去想三个问题:它前面的概念是什么?它后面的概念是什么?和它同级的概念是什么?比如学 useEffect,就去想:useState 是做状态管理的,useEffect 是做副作用的,它们之间的调度关系是什么样的?useEffect 的依赖数组和 useMemo 的依赖数组有什么内在一致性?useEffect 的清理函数和 componentWillUnmount 在 Fiber 架构下的行为有什么本质区别?
这三个问题想清楚,比读三篇文章有用得多。
前端领域的几条核心骨架
前端知识有几条贯穿始终的主线:
骨架一:JavaScript 执行机制
JavaScript 是单线程执行的
↓
单线程决定了异步模型的必要性
↓
事件循环机制:调用栈、任务队列(宏任务、微任务)
↓
Promise 是异步编程的解决方案
↓
async/await 是 Promise 的语法糖
↓
async 函数和普通函数的区别:async 函数总是返回 Promise
↓
await 的行为:暂停当前 async 函数的执行,等待 Promise resolve 后继续
↓
await 后面如果跟的不是 Promise,会自动包装成 Promise
↓
微任务先于宏任务执行:Promise.then() 是微任务,setTimeout 是宏任务
骨架二:浏览器渲染流水线
HTML 解析 → DOM Tree
↓
CSS 解析 → CSSOM
↓
DOM + CSSOM → Render Tree
↓
Layout(计算每个节点的位置和大小)
↓
Paint(绘制节点)
↓
Composite(合成层合并)
↓
reflow(布局变化)触发 repaint
↓
CSS 属性决定是否触发 layout/paint/composite
骨架三:React 更新机制
setState 被调用
↓
创建 update 对象,加入 update queue
↓
React 批量处理 updates(在事件处理函数结束时)
↓
Fiber 架构:render 阶段(可中断)和 commit 阶段(不可中断)
↓
lane 模型:不同优先级任务
↓
reconciliation:新的 React Element 和旧的 Fiber 对比
↓
Diff 算法:key 的作用
↓
commit 阶段:DOM 操作、生命周期、useEffect 触发
↓
useEffect 的清理函数在下一次 render 前执行
准备方式的转变:从"找材料"到"建骨架"
意识到自己准备方式有问题,是改变的第一步。接下来要做的不是停止学习,而是改变学习的结构。
第一步:停止继续堆材料
现有材料够用,需要的是重组,不是增加。把收藏夹关掉,把书单暂停,把"待看文章"的数量降下来。
第二步:画出自己的骨架图
拿出纸笔或者白板,列出自己最熟悉的三到四个技术领域——比如 React、JavaScript 异步、浏览器缓存、构建工具。对每个领域,画一条线,线上标出最重要的几个概念,概念之间用箭头连起来,表示"这个和那个有关系"。
# 骨架图示例:React 状态管理
[useState] → [状态更新] → [update queue]
↓
[批处理机制]
↓
[Fiber 架构] → [render 阶段] → [commit 阶段]
↓
[lane 模型] → [优先级调度]
↓
[useEffect] → [依赖数组] → [清理函数]
第三步:对着骨架图自检
对着这条线检查:哪些概念我能用自己的话讲五分钟?如果讲不到五分钟,说明理解不够深,需要回到基础材料重新学。如果能讲,但讲不出前后连接,说明知识还是散的,需要找连接。
第四步:对照骨架准备,而不是对照 JD
JD 上写的"熟练掌握 React 原理"不是让你去背答案的,是让你能在这个框架下讲出东西来。对着骨架准备,而不是对着 JD 逐条准备。
建骨架的具体操作
操作一:顺藤摸瓜
找到一个你觉得已经"差不多理解了"的知识点,比如 React 的 useEffect。然后问自己一连串"为什么":
- 为什么 useEffect 需要依赖数组?
- 为什么依赖数组变了会重新执行?
- 为什么有时候会死循环?
- 死循环和依赖数组的关系是什么?
- React 怎么检测依赖的变化?
- React 的比较是浅比较还是深比较?
- 依赖数组里的函数每次渲染都会变吗?
- useCallback 和 useMemo 怎么配合依赖数组使用?
这串"为什么"会把你带到 React 的调度机制、Fiber 架构、reconcile 和 commit 的阶段。
操作二:用自己的话讲出来
把你顺着"为什么"推导出来的这条线,讲给一个不懂的人听。或者对着手机录音,讲完自己听一遍。
如果你能把这个知识点从"我知道"变成"我能讲清楚",说明这个骨架已经建好了。
如果讲的时候卡住了,或者绕来绕去说不清楚,说明这个点还没理解透,需要重新学。
操作三:找同类项
每个知识点都不是孤立的。学会之后,主动去想:
- 它的同类概念是什么?比如 useEffect 和 useLayoutEffect 的区别?
- 它们有什么共同点?有什么不同点?
- 在什么场景下用哪个?
骨架建好之后的状态
骨架建好之后,你对知识的掌握会从"我知道这个概念"变成"我知道这个概念在整个体系里的位置"。
面试官问到一个问题,你不是从记忆里检索答案,而是顺着骨架往下走,走到对应的节点,把这个节点的知识输出出来。
比如问到 React 的批量更新,你不是背一个"React 18 自动批量更新"的答案,而是从 React 的 render 阶段开始,讲到 reconcile 过程,讲到 updates 队列,讲到批量更新的机制和边界情况。答案不是临时找出来的,是顺着骨架推出来的。
这种状态会让你在面试里更有底气。不只是能回答问题,而是能讲清楚问题。能讲清楚问题的候选人,在面试官眼里是加分的——说明你真的理解了这个机制,而不是只知道皮毛。
这一章想说的
"觉得自己没准备好"是大多数有经验工程师准备面试时都会经历的状态。这不是知识不够的问题,而是知识没有成体系、表达没有经过训练的问题。
解决方式不是继续堆材料,而是改变准备的结构:先把知识串成网,再对着这张网训练表达能力。
骨架建好之后,遇到新问题的反应会从"这个问题我没看过"变成"这个问题应该属于 X 领域,X 和 Y 有关系,所以可以从 Y 来想"。
接下来的章节会具体讲怎么建这张网、怎么训练表达、以及在工程化和项目经验这些更软的方向上怎么准备。