2024前端秋招面经:从准备到实战的完整复盘
2019年秋招结束快一个月了终于把论文初稿交掉可以静下心把这阵子的前端面经整理出来。先交代一下背景普通前端研究僧学校不算亮眼也没有大厂实习背书纯靠八月初到十月底这三个月一路投、一路面、一路补。前后投了三十多家公司收到面试机会的差不多一半真正走完流程的有13家最后手里攥着三个offer做了选择。这篇面经同步发在掘金的技术征文里也算给自己这段时间一个交代。我想先说清楚这篇文章适合谁看。如果你是大三或研二准备参加下一届秋招那这篇面经能帮你少走很多弯路如果你已经在一线写业务但想梳理一下前端核心知识点也可以顺着我的复习提纲过一遍如果你只是想看个热闹那也行但我尽量少讲虚的多写具体题目、具体流程、具体坑。1. 秋招前的准备简历、项目、刷题这三件事秋招不是从投简历那天开始的。我真正进入状态是在七月那时候论文开题刚过实验室的项目也告一段落忽然发现自己面前摆着三座大山简历没东西写、算法没系统刷、框架源码没细看过。所以第一件事不是海投而是先把这三件事理清楚。1.1 简历里最容易被追问的三处细节前端简历和别的岗位不太一样面试官特别喜欢顺着你写的项目一路问到底所以简历上每一个技术词、每一个项目描述都必须能扛得住追问。我见过太多人简历上写“熟练使用Vue”结果被问到“Vue的data为什么是函数”就卡住写“深入了解浏览器渲染机制”结果被问到“合成层是什么”就露馅。写上去的每一个字都要做好被问的准备。项目经历最好用“背景-动作-结果”的结构来写而不是写“我负责某某模块”。同一段经历不同写法效果差别很大。比如“我负责后台管理系统的权限模块”和“针对多角色后台场景基于路由守卫和动态路由表实现了按钮级权限控制把新增权限的配置成本从每次改代码降低到后台配置”面试官看到的是两种完全不同的候选人。我自己的简历里放了两个项目一个偏业务复杂度的后台项目一个偏工程化的组件库项目几乎挂在简历上的每一行技术点都在面试中被问到过。还有一个容易忽略的点团队规模和自己的角色要写清楚。面试官问你“这个项目是你一个人做的还是团队做的”不是随便问问他想知道在多人协作的情况下你怎么定义边界、怎么分工、怎么处理冲突这也是技术面里常见的能力考察方向。1.2 LeetCode 120题的刷题标签清单算法是我秋招前期最慌的一块。非科班出身大学只学过C语言基础刷题起步非常晚七月才开始。我没有盲目追求题量而是按标签分类刷我的LeetCode刷题记录大概是120题上下但每一题都至少二刷过。前端面试的算法难度整体来说低于后端但也不是随便考考。我整理了一套优先级比较高的标签清单数组与双指针盛最多水的容器、三数之和、移动零这类型是笔试高频。字符串大数相加、最长公共前缀、翻转字符串里的单词。链表反转链表、合并两个有序链表、环形链表这几道几乎是必做题。二叉树层序遍历、最大深度、最近公共祖先二叉树的题目一定要能手写不依赖IDE提示。栈与队列有效括号、用两个栈实现队列这些简单题是面试用来暖场的。排序与二分快排、归并、二分查找的边界条件能手写快排和归并很重要。动态规划爬楼梯、打家劫舍、最长递增子序列前端面试考到中等级别动态规划的概率不高但简单DP还是要会。我当时的心态是不追求难题怪题但高频题要做到十分钟内能写出无bug的版本。实际面下来大部分公司考的就是这个范围内的题目。1.3 给自己列的前端核心知识点复习提纲刷题之外更关键的是建立自己的知识地图。我给自己拉了一个前端核心知识点清单分模块过模块核心内容优先级JS基础原型链、闭包、作用域、this指向、Event Loop、深浅拷贝、类型转换极高浏览器渲染机制、重排重绘、缓存机制、存储方案、同源策略极高网络HTTP缓存、HTTPS、HTTP/2、跨域方案、TCP握手极高框架Vue响应式原理、虚拟DOM、生命周期、组件通信React Hooks、Fiber基础、setState高工程化Webpack构建流程、loader与plugin、Tree Shaking、代码分割高算法上述标签清单高手写代码防抖节流、深拷贝、Promise、数组方法实现极高每过完一个模块我就去找对应的前端面试题看用自己的话讲一遍讲不顺的地方就是知识点缺口。这个方法比光看不练有效很多倍。2. 前端基础考察JS、浏览器、网络不能含含糊糊前端技术面通常从基础能力开始这一轮能不能过决定了你后面有没有机会展示项目和框架能力。基础轮挂了往往是因为面试官觉得你“不稳”不是因为你不会某个偏门知识。2.1 高频JS考点复盘与答题思路JS基础是前端面试的压舱石我几乎每一面都被问到。高频考点集中在下面几块闭包几乎是必考。我记得有一道题是问“for循环里用var声明i然后用setTimeout输出i结果是什么怎么解决”这道题考察的就是闭包、作用域和块级作用域。先回答输出全部是同一个值再答用let替代var再深入一点可以讲闭包捕获的是变量而不是值面试官通常会很满意。原型链是另一个高频点。“new一个对象发生了什么”、“instanceof的原理是什么”、“如何实现一个继承”这种题属于一道能带出一串的。我习惯用链表的思路去理解原型链每个对象都有__proto__指向构造函数的prototype原型上找不到属性就继续沿着__proto__往上找直到Object.prototype.__proto__为null。这样表述既直观又不容易被绕晕。this指向和Event Loop也经常结合着考。Event Loop我总结了一个答题顺序先区分进程和线程再说同步任务与异步任务再说宏任务与微任务然后说浏览器一次事件循环从宏任务开始、执行过程中产生的微任务在本轮事件循环结束前全部执行完最后举例说明。async/await相关的题目也逃不掉本质上还是Promise和微任务。闭包、原型链、this、Event Loop这四个点建议不要停留在“看过”要能把概念用白话说给一个完全不懂的人听。面试官追问深了实际上考的是你有没有真正建立自己的知识结构。2.2 浏览器渲染机制与性能优化的一次完整回答“从输入URL到页面展示发生了什么”是前端面试的经典题目也是很多公司项目面、性能面问题的引子。这道题答得好不好很能体现一个人的知识体系完整度。我的标准答题链条是DNS解析域名拿到IP建立TCP连接发送HTTP请求服务器返回HTML浏览器边下载边解析HTML生成DOM树同时解析CSS生成CSSOM树两者合并生成渲染树然后计算布局、绘制到屏幕。这其中还要补充JS解析阻塞、CSS不会阻塞DOM生成但会阻塞渲染、async和defer的区别以及浏览器预加载扫描器等优化前提。面试官从这道题经常引申出性能优化问题比如白屏时间怎么优化、首屏加载资源怎么减少、为什么会触发重排和重绘。我建议把“重排重绘”单独整理改变几何属性会触发重排改变颜色背景会触发重绘用transform实现动画可以跳过重排用DocumentFragment可以减少DOM操作引发的重排次数。这类问题在项目组面试里几乎是保送题。浏览器缓存也值得一提。强缓存和协商缓存的字段我当时背得很熟但真正被问到“为什么需要缓存”、“怎么设计一个缓存策略”时才意识到背诵和理解的差距。建议至少要知道Cache-Control的常见取值、ETag和Last-Modified为什么同时存在、以及刷新页面和输入地址两种场景下缓存策略的差异。2.3 HTTP、HTTPS、跨域与安全的前端视角网络方面的考察前端不像后端问得那么深入但广度绝对不小。HTTP/1.1与HTTP/2的区别、HTTPS握手过程、跨域方案、XSS与CSRF这四块是我反复被问到的。HTTP/2多路复用是高频题。很多人回答说“一个连接多个请求”但面试官想听的是HTTP/1.1的队头阻塞问题、HTTP/2的二进制分帧层、同一个连接上并发多个流互不阻塞。我当时还额外提了头部压缩和服务端推送面试官点头的次数明显变多。跨域是前端特有的问题基本必考。JSONP的原理、CORS的简单请求与预检请求、代理转发在后端场景怎么配置、postMessage用于跨窗口通信这些问题都要能说清楚。其中CORS的预检请求是我被问得最多的细节什么条件下会触发options请求、Access-Control-Allow-Origin怎么动态配置都值得准备。安全类题目主要是XSS和CSRF。前端能做的最直接的事是CSP、HttpOnly、输入过滤、CSRF Token、SameSite Cookie。有一次面试官追问“如果Token被盗了怎么防御”我当时有点卡壳后来补了验证码、操作二次确认、水印溯源等方案。这个问题提醒我安全知识不能只背攻击类型还要想防御链路。3. 框架和工程化面试官问的不仅仅是API框架题是区分度最高的部分也是“八股文”最容易翻车的地方。背API没有用面试官稍微换个角度问就露馅。我自己的经验是无论你用Vue还是React都要挑其中一个深入底层另一个至少懂设计思路。3.1 Vue 源码层面的高频追问我的主力框架是Vue 2.x所以Vue相关的问题我准备得最足。响应式原理是必须过关的我的理解是Vue通过Object.defineProperty将data中的属性转成getter/setter组件渲染时读取属性会触发getter收集依赖属性变化时触发setter通知依赖更新。这里可以展开的细节很多比如Dep和Watcher的关系、为什么Vue 2无法监听新增属性所以要提供Vue.set、数组方法为什么需要拦截重写。computed和watch的区别也是高频题。我一般回答computed有缓存机制依赖的响应式数据没变就不会重新计算watch是监听指定数据变化后执行回调适合异步和开销较大的操作。面试官往往会顺着问computed是怎么实现缓存的这又回到依赖收集和脏值检查的逻辑上。还有几个容易被问但容易忽略的细节data为什么是函数、v-for为什么需要key、nextTick的原理、生命周期父子组件的执行顺序。尤其是nextTick我总结过Vue在数据变化后不会立即更新DOM而是把更新回调放进异步队列nextTick本质上是把回调推入微任务队列优先使用Promise、最终降级到setTimeout。这个细节面试官听到都会眼前一亮。3.2 React Hooks 与设计思路对比虽然我主力是Vue但React的问题也躲不掉。被问到最多的是Hooks尤其是为什么useState在多次渲染之间能保持状态、为什么Hooks不能在条件语句里调用。我当时的理解是React按调用顺序给每个Hook分配状态单元所以必须在每次渲染中用相同的顺序调用任何条件判断都会打乱顺序导致状态错位。React的setState同步异步问题也经常考。核心不是“异步”两个字而是批量更新机制在React事件处理函数中多个setState会被合并在原生事件和setTimeout中React 17之前走的是同步更新。这个问题我吃过亏一开始笼统回答“是异步的”面试官追问之后才发现理解浅了。虚拟DOM的diff算法在Vue和React两边都有考察。我建议先理解一个核心思路同层比较、key优化、用 tag 和 key 判断节点是否可复用不要纠结细节源码。能说清楚diff的复杂度为什么是O(n)以及key的作用就能拿到这题的及格分。3.3 Webpack 工程化与手写loader工程化考察集中在Webpack我当时给自己定的目标是能说清构建流程、能讲明白loader和plugin的区别、能写一个简单的loader。这三样做到位工程化的题目基本能覆盖七八成。构建流程可以简述为从入口开始解析模块依赖将JS/CSS/图片等文件交给对应loader处理再根据依赖关系生成chunk最终输出bundle。loader是文件处理管道plugin是事件钩子两者的区别面试官非常爱问。手写loader时我写过最简单的一个把源码中的字符串替换成另一个字符串只需要导出一个函数返回处理后的结果这个例子已经足够展示loader的工作方式了。Webpack性能优化也是常客Code Splitting、splitChunks、Tree Shaking、Loader缓存、DLL不再主流了但可以提。有一个容易被忽略的点是SideEffects字段的配置Tree Shaking能不能彻底生效和package.json中sideEffects有直接关系这个很多面经不会提但面试官可能很感兴趣。4. 十余家公司面试实录与套路拆解准备阶段和基础复习写得差不多了接下来进入正题讲讲我实际面试中的真实经历。下文会提到公司类型和面试轮次不会指名具体公司但过程和题目都是我亲身经历的。4.1 电商类公司一面基础二面项目三面HR的标准流程我面的一家头部电商公司整个流程非常标准。一面是简历面基础面没有算法全程都在问JS和浏览器。面试官是个很年轻的工程师问了Event Loop和浏览器缓存后就让我做了一道“实现深拷贝”的代码题要求在纸上写出处理循环引用的版本。这里我踩了一个很经典的坑只在纸上写了遍历对象并拷贝完全没考虑对象里有环的情况面试官提醒了一句“这个对象如果自引用会怎么样”我才反应过来马上补了WeakMap记录已拷贝对象的方案。面完出来我出了一身冷汗后来每次准备手写题都会默认面试官要考察边界情况。二面是项目深挖场景设计。面试官对着我简历上的权限管理项目追了很久菜单权限和按钮权限怎么设计的、后端返回什么样的数据、如果某个接口权限变了前端怎么同步。最后让我现场设计一个多角色权限系统的前端方案。这种场景题考察的不只是技术还有思考问题的条理性。我的回答思路是先明确用户与角色的关系再设计路由级和按钮级两套粒度的权限控制最后补上权限变更后的刷新策略。三面是HR面考察稳定性、薪资期望、为什么选择前端岗位。这一轮没有对错但建议提前想清楚自己的答案。被问“如果你手上已经有三个offer你该怎么选”时我当时的回答是看团队业务和技术沉淀HR表情还是比较满意的。4.2 社交内容类公司算法题量不小还考了手写Promise链我面试的一家短视频/社交大厂算法题量明显比其他公司大。一面就是远程在线笔试加面试笔试有两道题一道是“翻转字符串中的单词顺序”一道是“实现一个带并发限制的异步任务调度器”。第二道题我后来专门在博客上看到过其实是一个经典的前端并发控制题但笔试现场我写得并不熟练好在代码逻辑完整最终进入了后续面试。二面考了手写Promise.all这道题属于“以为会写、一写就乱”的类型。我第一次写时只考虑了resolve的情况忘了处理reject、忘了考虑传入非Promise值的情况。面试官没有直接提醒而是问“如果数组中某个值不是Promise你的实现会成立吗”我才反应过来。这也是手写题的标准套路功能实现只是第一步边界处理才是真正拉开差距的地方。这家公司还问了一个很特别的场景题设计一个无限滚动列表要求保证白屏时间稳定、内存不膨胀。基本思路是虚拟滚动固定可视区域大小只渲染可视范围内的条目通过监听滚动事件计算起始索引。还需要注意滚动事件要加防抖或使用requestAnimationFrame以及预留缓冲区避免快速滚动时白屏。这种题答出来之后面试官会明显对你更感兴趣。4.3 金融类公司算法偏基础、安全考得深、流程更长金融机构的面试风格和互联网公司差很多尤其是稳定性要求高算法题不会太冷门但安全相关的问题会考得很细。我面的一家金融科技公司一面问了两道题二叉树层序遍历和用两个栈实现队列都在我准备的范围内写得比较顺。二面的重点在安全问题。面试官围绕XSS反反复复追问了很多层从“什么是XSS”一路问到“如果过滤不严、用户输入里有执行代码的字符串怎么办”、“HttpOnly只能防止哪种攻击不能防止哪种攻击”、“CSP如何配置”。我当时的感受是金融公司对数据安全的重视程度确实远高于普通互联网公司如果你的目标岗位是金融科技方向安全这一块一定要认真准备不能只背概念。这家的HR面还问了家庭情况、是否有对象、未来是否稳定在这个城市发展准备阶段完全没想到会问这些好在我平时心态还可以没有被问懵。4.4 创业公司与中厂风格更野更看重能不能直接干活我还面了两家创业公司和一家中型上市公司的分支业务。创业公司的技术面普遍不按套路出牌有一家直接让我打开笔记本现场看他们一个组件库的代码问我哪里设计得不好、如果要重构怎么改。这种面试最考验真实水平因为没有标准答案。我当时从组件划分、Props设计、样式隔离、类型定义几个角度给出了建议聊到最后面试官说“还行能直接上手”。中厂的面试题相对务实。有一家问“如果项目上线后白屏了你怎么排查”考察的是线上问题处理能力。我的回答路径是先确认是不是新发版本引起再查是否有JS报错、是否有静态资源404、是否有接口返回异常导致前端崩溃最后用错误监控平台和用户复现信息定位。这类问题没有唯一答案但思路要完整最好结合自己线上真实的踩坑经历。面这种公司有一个好处反馈特别快。我下午面完晚上就收到结果不像大厂流程要拖一两个星期。所以秋招投递的时候不要只盯着头部公司中厂和值得去的创业公司反而可以考虑。多几家流程快的公司还能给自己增加一些信心。4.5 印象最深的一场“压力面”最后写一场印象最深的面试。那是一家不算太大的公司但面试官全程面无表情我每回答完一个问题他都要问“还有吗”一直问到我答不出来为止。这种压力面试很考验心态我当时差点崩盘但还是硬着头皮把能想到的边角料都说了出来。事后复盘发现那位面试官问的问题其实都不偏只是每一题都想要我往下挖。比如“跨域怎么解决”我答了CORS他就追问“CORS的预检请求是怎么发起的”我答了JSONP他就追问“JSONP为什么只能GET”。这些问题其实我答得不算好但最后一个环节他反而露出了一点笑容说我“至少没有乱编”那场面试最后也通过了。压力面有一个特点面试官在意的不是你全都会而是你在压力下的反应。遇到这类面试保持诚实承认不会比硬编答案更重要。5. 手写题与场景设计题这类题目拿来就能用秋招面到中后期我发现手写题和场景设计题几乎成了前端面试的标配。算法题还能靠LeetCode练手写题如果不专门准备真的容易在考场上乱写。5.1 高频前端手写题清单与写法综合我面的十多家公司和身边同学的反馈这份手写题清单基本覆盖了80%的考频防抖与节流防抖是事件触发后N秒内不再触发才执行节流是N秒内最多执行一次。不要只背定义要能写出带参数和立即执行版本。深拷贝要处理数组、Date、RegExp、Map、Set以及循环引用。用WeakMap记录已访问的对象这个点是必考的。Promise.all、Promise.race需要处理空数组和reject情况还要兼容非Promise值。数组方法实现map、reduce、filter、flat用reduce实现map是经常出现的新题型。绑定与继承自定义bind、寄生组合式继承。大数相加输入两个字符串返回字符串形式结果注意进位。函数柯里化支持一次性传入全部参数和多段传参两种情况。手写题的套路其实很明显先实现主流程再补边界条件最后考虑参数异常。建议每个手写题至少默写三遍做到闭着眼能写出来的程度。考试时如果紧张导致卡壳先写出功能主流程也能拿一半以上的分。5.2 带并发限制的异步任务调度器这道题我想单独拿出来说因为它在2019年秋招的面试里出镜率极高我身边有三个同学都被考过我自己的面试中也出现了变种版本。题目大致是有多个异步任务要求同时最多执行N个一个任务结束后自动执行下一个任务最终返回所有任务的结果。核心思路是维护一个正在执行的任务池和待执行的任务队列启动时先放入N个任务后续每次任务完成时从队列中取出下一个任务执行。这道题的实现不算难但有很多细节如何处理reject、如何保证返回结果的顺序和传入顺序一致、如何防止重复启动。我当时在面试里用了一个简单的计数器加递归实现没有额外依赖任何库。面试官比较满意但追问了一句“如果任务数组有上万个你的实现会不会有问题”这其实是考察内存和调度机制的意识我当时回答“可以采用流式处理不一次性把全部任务放入队列而是按批次消费”算是过了这关。5.3 场景设计题的五步答题框架场景设计题不像算法题有标准解但答题有框架。我用得比较顺的框架是五步走明确需求与边界、拆解核心问题、设计接口与数据结构、描述核心实现、再讨论优化方向。举个例子面试官让我设计一个图片懒加载库。我先确认需求延迟加载图片直到图片进入视口然后拆解核心问题怎么判断进入视口、怎么处理动态滚动容器、加载失败怎么降级。接口设计上我会给出一个LazyLoad类构造函数接收图片集合和配置项暴露update方法给动态交互使用。实现上用IntersectionObserver做核心监听兼容方案是滚动监听加getBoundingClientRect。最后再补充图片渲染前用占位符防抖动、加载成功后再解码、在低端机上控制同时解码的图片数量。这样一套答下来面试官通常不会再追问更多。6. 复盘与避坑如果可以再来一次面完最后一家公司已经是十月底手里握着三个offer本想长舒一口气但静下来复盘整个秋招发现有很多地方本可以做得更好。这部分写给正在准备秋招的人希望你们绕开我踩过的坑。6.1 投递策略提前批一定要尽早下手我八月上旬才开始投简历回头看已经算晚了。很多大厂的提前批在七月就启动提前批不通过还可以补录到正式批等于多了一次机会。我当时认识的一位同学七月底就拿到了提前批offer九月份整个人都在放松写论文而我那时候还在面试中心态上的差距特别明显。建议投递时做一个表格记录公司、岗位、投递时间、内推人、当前状态、面试时间、面试问题、结果。不要嫌麻烦信息量一大靠脑子根本记不住。我后期能用表格复盘每一场的得失全靠这个记录习惯。另一个很关键的策略是海投和精准投结合。海投是为了保底和练手但不要把所有心力都花在海投上。一定要挑出十家左右你真正想去的公司花时间针对性了解它们的业务和技术栈在面试中体现出你做过功课通过率会高不少。6.2 心态管理被挂真的不是世界末日秋招过程中至少有两家公司是我觉得自己稳了、结果一面就挂的那种挫败感非常真实。特别是看到同学已经进入终面而自己还在笔试时很容易陷入自我怀疑。后来我想清楚了一件事面试是双向匹配挂掉的原因可能只是团队当前需要的人和你的方向不对路。有一次我面试时聊得很好面试官也明确说“技术功底不错”结果隔了两天收到拒信后来通过内推人打听才知道是团队hc临时冻结了。所以被挂不等于实力不行更不要因此否定自己。我自己的心态调节方法是每面完一场无论结果如何当天晚上都花十几分钟记录这场面试里回答不好的问题然后立刻去查资料补齐。这样每一场面试都变成了一次学习机会挫败感会明显下降。6.3 最后想给后来人的三个建议第一前端基础永远是第一位的。框架会迭代热点会转移但JS、浏览器、网络这些底层知识不会过时。把基础打牢你学任何新框架都会快很多。第二手写题和算法题一定要动手写不要只在脑子里过一遍。我的经验是以为自己会了和真正能写出来之间大概差五道纸面练习的距离。第三项目经历要讲出“为什么”。不要只说你用了Vue和Webpack要说为什么选它、不用它有什么问题、遇到难点是怎么做决策的。面试官想看到的不是知识点罗列而是你的思考方式。我在秋招最后一段时间总结出的一个体会面试本质上是一场高质量的信息交换。你展示自己面试官也在展示团队。与其把精力花在焦虑上不如认真准备每一场然后坦然接受所有结果。希望这篇面经能帮你在准备前端面试的路上省一些时间少踩一些我踩过的坑。