ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

前端面试“八股文”背后:深度不足的表现与提升建议

2026/8/30 8:17:48 拓冰建站 浏览量
前端面试“八股文”背后:深度不足的表现与提升建议 最近一段时间陆陆续续面了不少公司也帮朋友做了几轮模拟面试加上自己在工作里带人、做技术评审越来越有一种强烈的感受现在前端面试的“八股文”背得越来越溜但真正问到技术深度的时候很多候选人甚至个别面试官对底层原理的把握其实是不到位的。我并不是说八股文没有价值。事实上八股文是知识面的“索引”一个连event loop、闭包、diff算法都说不清楚的人很难让人相信他做过有质量的前端项目。但问题在于很多人把“背得出题”当成了“懂原理”而不少面试官也停留在“问得出题”的层面没有继续往下追问“为什么”。这篇文章我不想站在“面试官”或者“候选人”任何一方去批判谁而是想以一个从业者的视角把这些年在面试中观察到的“深度不足”现象掰开揉碎聊一聊。我会结合具体的面试题、具体的回答场景以及背后的原理分析说说问题到底出在哪里以及我们该怎么去应对这种局面。无论你是准备跳槽的候选人还是需要招人的团队 leader这篇文章应该都能给你一些参考。1. 前端八股文的“深度”到底是什么1.1 八股文不是洪水猛兽但它有分层我见过很多人写面经把“八股文”三个字当成贬义词好像一问底层就是在“卷”。但我自己的看法是八股文本身是分层的不能一概而论。最基础的一层是语言和平台层面的知识点。比如var、let、const的区别和的差异this的指向规则Promise的状态机这类。这些内容几乎是 JS 这门语言的“公约数”不管你在什么公司、做什么业务都得搞清楚。这一层如果不过关那确实说明基础不牢。第二层是框架和工程体系层面的机制。比如React的fiber架构、diff算法、setState的批处理Vue的响应式依赖收集、nextTick的实现webpack的构建流程、HMR的原理、tree-shaking的条件等等。这一层已经是“职业前端”和“能写页面的人”之间的分水岭了。第三层是跨领域的融会贯通。比如你能不能用浏览器渲染原理去解释requestAnimationFrame为什么比setTimeout更适合做动画能不能用事件循环去解释setTimeout(0)的不可靠性能不能用HTTP 缓存的规则去设计一个前端资源发布方案。这一层没有明确的八股文题目完全靠平时的积累和思考。问题就出在这里。很多候选人停留在第一层把第一层的题背得滚瓜烂熟一部分人能说到第二层但也只是“背结论”真正能到第三层的人我面了这么多确实不多。更扎心的是有些面试官自己也只是停留在第一层问完和、闭包是什么、数组去重怎么写就不知道该问什么了。1.2 “深度不足”最典型的表现会背定义不会讲场景我在面试里最常遇到的一种情况是候选人能把闭包的定义背出来——“函数内部访问外部变量”但当我问他“闭包在实际项目里到底用来干什么你写过哪些闭包的代码它和普通函数在内存表现上有什么区别”的时候就开始支支吾吾了。之所以会这样我总结下来问题不是出在候选人“不努力”而是出在学习路径和考核方式上都过度依赖“题目-答案”的范式。大家刷题的时候看到的都是“解释 xxx 概念”而不是“你在项目里是怎么用 xxx 解决问题的”。一旦知识点脱离了场景它就变成了单纯的“背诵文本”谈不上理解。比如闭包最常见的实际场景是函数防抖和节流。你自己手写一个debounce你就会理解为什么返回的函数能一直访问到timer这个变量为什么这个timer不会因为函数执行完毕就被销毁。你也会理解如果这个debounce用在 React 组件的useCallback里依赖数组到底该怎么写为什么依赖不对的时候防抖会失效。这才是“理解闭包”而不是“会背闭包”。所以我在后面的面试里只要有时间都会尽量把八股文题目往场景上引。这不是要故意刁难候选人而是因为只有场景才能检验一个人是否真的理解了这个知识点的来龙去脉。2. 我亲眼见到的几个“深度不足”现场2.1 事件循环背得出“宏任务、微任务”画不对执行顺序关于事件循环最经典的八股文题就是问执行顺序给出一段代码让你说出打印结果。这种题我几乎每次面试都会问因为它是 JS 运行时最核心的机制之一而且它足够“硬”——会就是会不会就是不会。让我印象很深的一个例子是一个自称“有三年 React 经验”的候选人。我问了下面这段代码console.log(script start); setTimeout(() { console.log(timeout 1); Promise.resolve().then(() { console.log(promise 1); }); }, 0); Promise.resolve().then(() { console.log(promise 2); }); setTimeout(() { console.log(timeout 2); }, 0); console.log(script end);他很快给出了答案script start、script end、promise 2、timeout 1、promise 1、timeout 2。这个答案完全正确。于是我又追加了一个问题“那如果我在promise 2的微任务里再放一个setTimeout(0)它的打印顺序会发生在timeout 1之前还是之后为什么”他想了想说应该在timeout 1之前因为微任务先执行。这个答案其实也对了但当我继续问“浏览器是怎么决定先执行宏任务还是先执行微任务的微任务队列是在什么时候被清空的是一次性清空还是只清空一个”的时候他说不上来了。这个案例非常典型。背结论的人知道“先微任务后宏任务”但不知道“每个宏任务执行完之后JS 引擎会去清空微任务队列”。他不知道在一次事件循环里宏任务是“一个一个执行”的而微任务是“一队一队清空”的。这导致他一旦遇到稍微复杂一点的嵌套代码就只能凭感觉蒙答案。“事件循环”这个知识点我们不应该只停留在“背顺序”而应该在脑海里建立一张完整的时序图当前宏任务执行 - 执行栈清空 - 检查微任务队列 - 全部清空微任务 - 渲染机会requestAnimationFrame 回调- 取下一个宏任务。把这些串起来再去分析代码执行顺序基本上就不会错。而且这样的理解方式还能帮你解释很多更复杂的工程问题比如“为什么setTimeout的定时在后台标签页会被节流”、“为什么async/await写不好会造成性能问题”等等。2.2 闭包与内存知道“闭包”是什么不知道“闭包”会带来什么上面已经提到闭包这里我想再展开说说。闭包是另一个“看起来人人都会实则深度差异巨大”的知识点。基础题通常是什么是闭包经典回答函数内部访问外部变量内部函数被返回并在外部引用后形成了对父级作用域的引用所以父级作用域不会被销毁。但通常在业务开发里真正和闭包相关的坑是意外持有导致的内存泄漏。比如下面这段代码function createApp() { const heavyData new Array(10000000).fill(x); document.getElementById(btn).addEventListener(click, function onClick() { console.log(clicked); }); }onClick这个函数虽然没有直接引用heavyData但是因为它和heavyData在同一个作用域里闭包会把这个作用域整体保留下来。只要事件监听器不解除heavyData就永远无法被回收。这在 SPA 应用里很常见——页面切换的时候如果removeEventListener做漏了内存就会悄悄涨上去。我也用这道题考过不少候选人。能答出“闭包导致内存泄漏”的不少但能进一步说出“什么情况下闭包一定会导致内存泄漏是不是所有闭包都会泄漏”的人就很少了。其实只要闭包函数已经没有任何引用它本身就会被回收不会泄漏只有当你把闭包函数挂在一个长期存活的对象上全局变量、事件监听器、定时器回调等才可能出现泄漏。我给大家一个自查的方法当你在代码里写了一个addEventListener或者setInterval随手想一下“这个回调函数被谁持有它的作用域里有没有大对象”这个习惯养成之后你就会理解为什么现代前端框架要在useEffect里返回一个清理函数为什么要用useCallback和useRef控制依赖。这些都是闭包知识的实际应用。可惜的是很多候选人画不出这条链路。他们脑子里只有“闭包 能用”或“闭包 会泄漏”这两个孤立结论中间的推理过程是缺失的。2.3 React 渲染优化都在说 memo但说不清什么时候该用React 生态是八股文的重灾区。useMemo、useCallback、memo、diff、Fiber随便哪个都能拉出来考一考。但真正让我觉得“深度不足”的不是候选人说不上这些 API而是他们不知道这些 API 到底是在解决什么问题。我一般会问这样一道题父组件里有一个useState的计数器和一段很耗时的渲染列表点击按钮会让计数器加一进而触发父组件重渲染。子组件接收一个props并且完全不依赖父组件的 state。请问子组件会跟着重渲染吗如何避免memo是必须的吗如果用useMemo包住子组件的 JSX和用memo包住组件有什么区别这道题把“React 函数组件在什么情况下会重渲染”这个核心机制全考了。能完整答上来的人大概率真的理解 React 的渲染流程答不上来的人通常都停留在“用memo可以优化性能”的层面。说句实话在大多数业务场景里memo和useCallback真的没那么重要。与其纠结这些 API不如先搞清楚一件事你的组件为什么会重渲染在 React 中函数组件每渲染一次就是“执行一次函数”。只要父组件函数重新执行了子组件函数也会跟着重新执行不管它的props有没有变化。memo做的事情是让 React 在子组件外部做一个“浅比较”如果props的引用都没变就跳过子组件函数的执行复用上一次的渲染结果。这里关键来了如果父组件每次渲染都生成一个新的数组/对象/函数传给子组件那么即使子组件被memo包住了浅比较也会认为props变了导致memo失效。所以说“memo必须搭配useCallback/useMemo才能发挥效果”——不是八股文是真正从机制推导出来的结论。能推理到这一层的人在遇到“为什么我加了 memo 没效果”这种实际 bug 时就能很快定位问题而停留在“背概念”的候选人遇到这个问题大概率只能console.log盲猜甚至回一句“可能 React 版本有 bug”。2.4 浏览器渲染机制知道“重排重绘”答不出优化场景前端面试十道题里有八道会考浏览器渲染。这是我最喜欢问的方向因为它横跨HTML、CSS、JS三门语言而且直接关系到页面性能。面试里常见的问题是什么是重排reflow和重绘repaint它们有什么区别如何减少重排标准回答一般是重排是计算元素几何位置重绘是绘制像素重排一定会导致重绘重绘不一定导致重排减少重排可以用transform代替top、left动画等等。这套答案背下来很容易但当我追问“为什么transform不会触发重排它用的是哪个合成层什么时候transform也救不了你”的时候绝大多数人都会卡住。实际上transform不触发重排的根本原因在于浏览器把元素放到了独立的合成层上transform的变化只是对这个层做 GPU 合成变换不涉及布局计算。这就好比你有一张打印好的海报你想把它往右挪一点你不需要重新排版整张海报只需要把海报物理移动一下就行。但这里面有一个很关键的前提如果这个元素所在的合成层本身非常大或者页面上有大量合成层GPU 会吃不消照样导致卡顿甚至比重排重绘更严重。这就是为什么“用transform做动画就一定流畅”是个错误结论它只对了一半。大家在复习这个知识点的时候如果能多问自己几个“为什么”比如“为什么transform不触发重排”“为什么position: fixed某些时候会失效”“为什么content-visibility: auto可以跳过屏幕外元素的渲染”你的理解深度就会完全不同面试的时候也自然能说出比别人更立体、更有层次的内容。3. 为什么会出现“深度不足”的局面3.1 题库越来越新但知识体系没有随题而长观察下来现在“前端八股文”的题库迭代速度是非常快的。从早期的DOM操作、闭包、原型链到后来的Vue/React 生命周期、diff 算法再到现在的微前端、性能优化、TypeScript 类型体操题目越来越花哨。但问题在于很多候选人的知识体系是“块状”的不是“网状”的。他们背了一堆“块”但块和块之间没有连起来。比如背了 “TypeScript 的infer关键字”却不知道它其实是和“函数返回值类型的推断”相关的背了 “React 的useSyncExternalStore”却不知道它解决的其实是“外部 store 和并发渲染的撕裂问题”。知识碎片化导致了一个很典型的面试现象单独问点都能答上一旦把几个点串起来或者换一个业务场景立刻就“卡壳”。我在一面里常用的一道组合题是用Web Worker处理大量数据的计算计算完成后把结果传回主线程渲染一个很长的列表。请说说这个过程中有哪些性能瓶颈分别怎么优化这道题其实没有标准答案它考察的是Worker 通信、大数据渲染、浏览器内存、事件循环等多方面知识的综合运用。能答好的人一定是能把“块”连成“网”的人答不好的人通常就是被“块”困住的人。3.2 面试官段位参差有些人的题目是从面经里抄的这个问题不太有人愿意说但作为一面面试官我观察到的现象是确实存在一部分前端面试官他们的考核方式就是“题库搬运”。这类面试官手里往往有一套自己当年找工作时的面试题合集或者是一个“前端知识图谱”的 checklist。面试的时候他们按着 check item 一个一个问事件循环、闭包、原型链、盒子模型、flex 布局、浏览器缓存、webpack 优化……每个问题只要候选人能说出“关键词”就算过关。至于候选人回答里的漏洞、混淆、甚至错误的概念他自己也听不出来。这就导致一种非常荒诞的循环面试官水平不足招进来的人水平也跟着打折扣这批人再过两年也成为面试官继续用固定题库筛人。整个行业的技术深度在一部分公司里不升反降。我当然知道不是所有公司都这样很多一线大厂的面试还是很扎实的会有非常细致的追问环节。但“八股文面试”和“深度面试”的差别确实肉眼可见地存在。有些公司一面问的都是概念题二面让写算法三面聊项目——看起来流程很规范但实际上每一轮都停留在“你背过没有”的层面没有人真正去验证候选人“能不能想清楚一个问题”。3.3 候选人的应试策略放大了问题还有一方面也值得说就是候选人的应试策略。现在的面经文化太发达了很多候选人花大量时间刷题、背题这本身没有错。但如果你的重心全放在“怎么应付面试官”而不是“怎么把原理学透”上面短期里也许能过面试长期来看反而是给自己埋雷。最典型的例子是“手写 Promise/A” 这道题。网上有很多版本的“标答”全都标注着“高频题”。于是很多候选人不管三七二十一先把代码背下来面试的时候默写一遍。但当我追问“你实现的.then为什么返回了一个新的 Promise如果直接return this会有什么问题resolvePromise里为什么要加called标志”的时候就露馅了。我真心觉得候选人应该把面试准备当成一次系统性学习的过程而不是刷题过关。那些反复被问到的点比如Promise、组件通信、工程化配置都是这个行业真正需要的核心能力。你花了一周时间把它们真正搞懂收获的是一辈子的职业基础你花了一周时间把它们背下来收获的可能只是入职三个月的试用期。4. 如何提升“深度”给候选人、也给面试官的建议4.1 给候选人别背题去推演我理解大家找工作的压力也理解“八股文”是绕不开的筛选手段。但我的核心建议是背题可以但要在背题之后加一步“推演练习”。具体来说看一道题不要急着看答案先自己回答一遍然后问自己三个问题这个结论是从什么前提推导出来的如果环境改变比如从浏览器换成 Node从 Vue2 换成 Vue3结论还成立吗如果不成立变化在哪这个知识点和我之前做过哪个项目、遇到过哪个 bug 有关举个例子你在背“webpack的tree-shaking依赖 ES Module 的静态结构”时可以顺手推演一下为什么CommonJS不行因为require是运行时执行、可以写在条件语句里的编译器无法静态确定你到底引用了哪些导出而import必须在顶层、模块依赖关系是静态确定的所以可以分析出哪些导出没用。这样一来你不仅记住了 “tree-shaking 用什么语法”还明白了“为什么用这个语法”、“换成 CJS 为什么不好使”。这种“推演习惯”一旦养成你再看问题的方式就完全不一样了。你不再是“记住了一个知识点”而是“推导出了一个知识链”面试的时候哪怕突然紧张也能顺着逻辑说下去而不是卡在“忘了关键词”上。4.2 给面试官多问“为什么”少问“是什么”作为前端 team lead我也经常帮团队设计面试题。我一直强调一点面试官的作用不是打分而是帮候选人把脑子里的知识“展开”。如果候选人能答对“宏任务微任务的执行顺序”你要继续追问“为什么微任务要先执行完”如果候选人能答出“useMemo可以缓存计算结果”你要继续追问“缓存的是什么什么时候缓存会失效”如果候选人能说出“script标签加defer可以延迟执行”你要继续追问“defer和async的区别是什么如果两个defer的脚本之间存在依赖关系会出问题吗”。深度从来不是靠问一道“偏题怪题”能问出来的而是靠追问“为什么”一层一层挖出来的。一个只知道背答案的人最多能扛住第一层追问一个真正理解原理的人能一路回答到“运行时”“编译器”“网络协议”这些底层领域去。另外我还想提一个建议面试官在评价候选人的时候不要把“背出了答案”直接等价于“能力强”。你要看他回答时的状态是流畅但不过脑还是边思考边推理是直接给结论还是先分析前提再说结论这中间的差别比答案本身更能说明问题。4.3 给团队把评审当成常态化机制而不是面试才测深度最后也想说点团队层面的东西。面试应该是“深度的抽样”不应该是“深度的全部”。如果一个团队平时根本不聊技术细节只在招人的时候考深度那大概率招不到满意的人也留不住有想法的人。我自己在团队里推动的两种常态化机制效果非常不错每周一次“原理分享”不限主题不限难度但要求讲清楚“一个机制的完整链路”。比如“从输入 URL 到页面展示的整个过程”从 DNS、TCP 到渲染流水线每个环节要能回答大家随时的追问。Code Review 时多问一层“为什么”不是只指出“这里写的不对”而是问“为什么要这样写如果换一种写法会有什么区别”如果写代码的人自己说不清楚那就一起查资料弄明白。长期坚持下来团队的平均技术深度会肉眼可见地提升面试的时候也会轻松很多——因为候选人面对的是一群真正懂行的人大家能聊到一块去而不是互相演背题。5. 我的真实感受与后续打算说了这么多“深度不足”的问题我再聊几句个人体会。我见过不少候选人笔试做得漂漂亮亮面试对答如流但一到实际项目里就各种踩坑——因为“背”和“懂”之间的距离只有“踩坑”才能弥补。反过来我也见过一些候选人八股文基础一般有些概念甚至说得磕磕绊绊但你能感觉到他在思考他在试图用已知的东西去推导未知的东西。这两种候选人如果让我选我大概率会选后者。原因很简单前端的知识更新太快了。你今天背熟的那套八股文过两年可能就变了但你的“理解能力”和“推理能力”是永远不会过时的。所以我真心建议大家在准备面试的时候不要只盯着“高频题”也别总想着“速成”。遇到一个概念多问几句“为什么”多想想“它解决的问题是什么”多联系一下自己在项目里的实际场景——这个过程可能慢但它的收益是长期的。后面我打算写一个系列文章专门挑一些高频的“八股文”题目一篇一篇地拆解它们背后的“为什么”尽量把那些网上搜不到、只能靠实战踩坑才能理解的细节讲透。如果你在面试或者平时工作里遇到过一些“看起来很基础、但细想很迷糊”的问题欢迎一起讨论交流。踩过多少次坑之后你就会明白前端这个行业深度不是靠背出来的是靠一个个问题“追”出来的。