ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

前端混子面进百度:从八股文到项目深挖的面试复盘

前端混子面进百度:从八股文到项目深挖的面试复盘 事情是这样的。我在上一家公司待了快两年属于那种“文档在手、天下我有文档一关、直接抓瞎”的前端。圈里人管这个叫混子我认。手上负责的页面不算少但论深度也就是能跑、能上线、不出大事故的水平。某天关系不错的同事发来一条消息说百度某个前端组在招人岗位要求写着“三年以上经验、有大型项目优先”我掰手指一算年限刚好卡线。他问我投不投我说投呗面挂了又不扣工资万一过了呢。结果从简历筛选到 HR 面前后折腾了大半个月我居然一路走到了最后。先说结论这轮面试让我最大的感触是基础前端八股文真的有用但只靠背八股文绝对过不了。整个过程里面试官问的东西大部分是网上能搜到的前端面试题但追问的深度和我平时刷题时想的完全不是一个量级。这篇文章我不打算写那种“标准答案汇总”而是按照我真实的面试轮次把每一轮问了什么、我当时怎么答的、哪些答崩了、哪些其实踩到了得分点原原本本捋一遍。适合正在准备前端面试、尤其是打算冲大厂的朋友参考也适合那些觉得自己技术一般但想试试水的“混子型选手”——别怕混子也有混子的打法。1. 开篇定调我这个「混子」是怎么混进百度面试间的1.1 我的技术自画像混在哪、不混在哪既然叫混子我得先老实交代一下自己的技术水平不然大家以为我在凡尔赛。我在上一家公司做的是偏业务型的前端Vue 2 为主后来项目局部升级过 Vue 3但组合式 API 用得不算深。UI 库主要用 Element UI 和 Ant Design Vue日常开发就是写页面、调接口、改 bug偶尔涉及一点前端工程化配置比如改 webpack 的 loader、调一下 babel 插件但你说让我从零搭一套完整工程我真不行。混的地方很明显原理层面一知半解。我用过 Vuex但说不清它的响应式在插件层面是怎么注入的我用过 webpack但只能说出 entry、output、loader、plugin 这些名词我也写过性能优化无非就是懒加载、压缩图片、加缓存再深一点就露怯。不混的地方是业务理解力和排查问题的能力还凑合。因为常年跟产品、后端、测试battle我养成了一个习惯遇到问题先自己复现、再二分定位、最后看源码或者文档确认这个能力在面试里意外成了加分项。1.2 简历与面试机会混子的简历怎么包装很多混子同学最头疼的就是简历没东西写。我也是。项目经验就那么几个后台管理系统总不能写“我写了一个商城后台”吧。我当时的策略是不写功能写问题和方案。比如有一个项目表格渲染一万条数据卡到爆我优化成了虚拟滚动那这个项目就是“基于虚拟滚动的海量数据展示方案设计”还有一个项目客户要求上传大文件我用 web worker 在浏览器端做了文件分片和哈希计算那这个项目就是“基于 Web Worker 的大文件分片上传实践”。面试官看到这样的表述第一反应不是“这人在写业务”而是“这人解决过具体问题”约面的概率会大很多。简历上不要撒谎但可以把做过的事用一种更有技术含量的方式表述出来。我后来复盘发现正是这两个项目点成了二面面试官深挖的主线。1.3 面试前的突击计划一周时间我是怎么安排的从投出简历到收到一面通知中间大概有一周多。我没法辞职全职复习只能每天晚上抽两三个小时突击。我的复习顺序是先看高频前端面试题和前端八股文再对着自己简历上的项目写故事。八股文主要过了一遍 JavaScript 基础闭包、原型链、this、事件循环、浏览器原理缓存、渲染、跨域、Vue 响应式原理和组件通信方式还有手写代码题防抖节流、深拷贝、Promise 相关。背诵部分其实网上资料很多我用的就是一个语雀文档配合 debugger 实际跑一遍效果更好。复习到后面我发现一个规律面试官问八股文不是为了考你背得熟不熟而是想看你能不能把知识点跟实际场景联系起来。所以我把每个八股文知识点都强行造了一个业务场景比如“节流用在滚动加载”“闭包用在防抖和柯里化”后面面试的时候确实用上了。2. 一面基础题轰炸混子差点当场现原形2.1 面试节奏40分钟从闭包问到事件循环一面约在下午两点视频面面试官看着挺年轻应该是组里比较核心的开发。开场没有太多自我介绍环节简单问了一下项目就直奔主题大概 40 分钟整体节奏很快。前半段是一些常规八股文比如“说说闭包是什么有哪些应用场景”“原型链怎么理解”“this 指向问题”“数组去重有哪些方法”。这些我背过答得还算顺但后来我才发现面试官真正想听的不是定义而是“你什么时候用过”。问到闭包的时候我举了防抖和节流的例子面试官明显来了兴趣顺势让我手写一个防抖——这就是背题和实际动手的区别了我那会儿手一抖差点把防抖和节流的触发条件搞反。后半段上了两道代码输出题都是事件循环相关。第一道大概是console.log(script start); setTimeout(() { console.log(setTimeout); }, 0); Promise.resolve() .then(() { console.log(promise1); }) .then(() { console.log(promise2); }); console.log(script end);这个我背过很多遍知道输出顺序是 script start、script end、promise1、promise2、setTimeout解释的时候把微任务和宏任务的优先级说了出来。但接下来他变了个花样问“如果 setTimeout 的延时改成 1 毫秒输出顺序会不会变”我当时就有点懵。后来想想他的意思是要讲清楚宏任务队列的执行时机和定时器的最小延时这其实前端面试八股文里常考但我当时没答到点子上只说了“不一定要看执行顺序”。2.2 让混子翻车的三道手写题防抖、深拷贝、Promise.all一面最刺激的环节是手写代码。面试官直接在共享文档里出了三道题前两道我磕磕绊绊写出了个大概第三道直接卡住这里详细说说。第一道是手写防抖函数要求支持立即执行选项。我一开始写成了节流的样子被面试官点了一下“你再想想你这段代码是防抖吗”我赶紧改回来。最终版本大概是function debounce(fn, wait 300, immediate false) { let timer null; return function (...args) { const callNow immediate !timer; if (timer) clearTimeout(timer); timer setTimeout(() { timer null; if (!immediate) fn.apply(this, args); }, wait); if (callNow) fn.apply(this, args); }; }写完之后面试官追问了两个问题为什么要用apply为什么用timer null而不是clearTimeout之后直接赋初值。这两个都是我平时没细想的点第一问还好知道要绑定 this 和传参第二问我支支吾吾他就直接解释了置空 timer 是为了让下一次 immediate 判断生效不然 callNow 永远都是 false。这个细节后来我记下来了确实是防抖实现里容易漏的点。第二道是深拷贝要求考虑循环引用、Symbol 和 Date。我平时背过很多版深拷贝但现场写的时候还是只能写出JSON.parse(JSON.stringify(obj))然后在面试官的引导下补了递归。注意深拷贝的递归版本判断对象类型时不要只写typeof obj object还要排除 null并且要用 WeakMap 来保存已经拷贝过的引用否则对象里面有循环引用会直接爆栈。后来我写出了一个支持基础循环引用的版本但对 Symbol 和 Date 的处理是在提示下才写出来的。这道题我只能算拿了三分。第三道是手写Promise.all要求支持数组项不是 Promise 的情况并且错误要 reject。我现场写了基础版但忘了一个关键点结果的顺序要和输入的顺序一致不能用 Promise 完成的先后顺序来 push。面试官说“你的代码能跑但结果顺序是乱的”我这下才反应过来。回看这段自己确实太混了平时用Promise.all用得飞起但从来没想过它的内部实现要保证顺序。2.3 CSS 与浏览器问题真不是背个八股就行一面中间还穿插了一些 CSS 和浏览器的基础题。CSS 问了“flex: 1 是什么含义”和“实现一个左侧固定、右侧自适应的两栏布局”。flex 那个我答得还行说了flex-grow: 1; flex-shrink: 1; flex-basis: 0%但面试官追问“flex-basis 默认值是什么”我答错了默认应该是 auto。这个知识点不偏但属于容易忽略的细节。两栏布局我提供了一个 float 加 margin 的方案面试官又问“还有什么方案”我说 flex他说“还有吗”我一时没想起来 grid。其实这些都是前端面试常客我的问题在于只准备了答案没有准备“多个方案横向对比”所以每道题只能说出一种解法给面试官一种“知其然不知其所以然”的感觉。浏览器部分问了强缓存和协商缓存的区别还问了Cache-Control有哪些常见字段。这个我工作中常跟后端对接口时研究过答得比较细包括max-age、no-cache、no-store、must-revalidate以及ETag和Last-Modified的优先级。我觉得就是这部分拉回了一点印象分让面试官觉得这个人虽然手写代码拉胯但工程常识还是有的。一面结束后我的感受是大概率挂了。因为手写题太拉胯而且有些基础细节答得很虚。结果第二天 HR 告诉我一面通过了我后来分析可能是因为项目经验描述比较贴合岗位需求加上网络和缓存那块答得不错面试官给了个 borderline。3. 二面项目深挖与原理拷问没有项目就只能挨打3.1 项目复盘混子项目里唯一能拿得出手的模块二面约在一面后第三天这次面试官明显资历更老问的问题完全围绕着简历上的项目。我已经反复准备了两个主线项目大文件分片上传和表格虚拟滚动。先说大文件分片上传。这个项目我做的时候主要用的是 web worker 来计算文件的md5哈希然后把大文件切成固定大小的分片逐个上传全部上传成功后后端合并。面试官听完我的介绍连珠炮似的问了几个问题为什么要在 worker 里计算哈希直接在主线程算不行吗分片大小是怎么确定的为什么选 5MB 而不是 10MB 或 1MB如果一个分片上传失败怎么处理要不要重试文件的唯一标识怎么生成如果两个文件内容一样但文件名不同算一个文件还是两个文件第一个问题我答得还行说计算大文件哈希会阻塞主线程导致页面卡顿和滚动掉帧所以放到 worker 里。第二个问题我其实没仔细想过当时就是拍脑袋定的 5MB面试官追问后我硬编了一个理由网络波动大太小会频繁请求太大会导致单次失败重试成本高。这个回答勉强算合理但被面试官听出了我没有做过实际压测。他补了一句一般会根据网络环境和文件大小动态调整分片大小有些方案会在秒传时先用 HEAD 请求咨询后端已存在的分片。这句话被我记到了笔记里。第三个问题我答了失败重试 重新上传该分片的方案面试官追问“并发上传分片的话怎么控制最大并发数”我说可以用 p-limit 之类的库或者自己维护一个并发池他就没继续追。第四个问题我答的是用内容哈希作为文件唯一标识所以两个文件内容相同但文件名不同会被识别成同一个文件秒传直接返回结果。这块我比较熟因为他问的正好是我做过的核心逻辑。3.2 性能优化从 Network 面板到 Lighthouse 的实战回答项目深挖之后面试官很自然地把话题引到了性能优化上“你在这个表格虚拟滚动里除了虚拟列表还做了哪些前端性能优化”我当时心里一紧因为简历里写了“首屏加载优化”但实际做的比较浅。我回答了几个点路由懒加载、组件异步加载、图片懒加载、打包时关闭 sourcemap、公共依赖抽成 CDN。面试官表示认可但接着问了一句让我有点慌的话“那你有没有真正研究过首屏性能指标比如 FCP、LCP 这些你知道它们分别代表什么吗”好在我在面试前一周刷到了一个关于 Core Web Vitals 的文章勉强能说出来FCP 是首次内容绘制LCP 是最大内容绘制LCP 通常比 FCP 更能反映用户感知的加载速度。面试官还追问了怎么优化 LCP我说了三个方向优化图片体积和格式、预加载关键资源、减少首屏 JavaScript 体积。他点点头没有再深挖。这轮的小心得是面试官并不指望你把所有性能指标说得倒背如流但作为一个有项目经验的前端你需要对自己项目里做了哪些性能优化有清晰的量化认知比如图片减少了多少字节、LCP 降低了多少毫秒哪怕只是估算也比只说“我做了懒加载”强得多。提个醒如果简历上写了“性能优化”四个字一定要准备一个可以量化的case不然面试官只要追一句“优化前多少、优化后多少”就很容易暴露出你只是嘴上说说。3.3 Vue 原理与响应式背了那么久终于用到了一次二面后半段基本是 Vue 原理的天下。面试官看了我的项目是用 Vue 2 写的但 JD 要求里有 Vue 3于是从 Vue 2 一直问到 Vue 3。他先问 Vue 2 响应式原理。这个我熟Object.defineProperty 对每个属性做 getter/setter 劫持实现依赖收集和派发更新。他接着问“数组的响应式是怎么处理的”我说 Vue 2 重写了数组的七个方法push、pop、shift、unshift、splice、sort、reverse然后他问“为什么直接通过下标修改数组不能触发视图更新”我回答是因为 defineProperty 只能劫持对象属性而下标修改没法触发。这个答得还算顺。然后他问 Vue 3 和 Vue 2 的响应式有什么区别。我答了 Proxy 和 defineProperty 的区别Proxy 可以拦截对象的增删和属性修改不需要像 Vue 2 那样遍历对象属性还可以拦截数组索引赋值所以不需要 hack 数组方法。面试官追问“Proxy 的兼容性怎么看”我说 es6 之后现代浏览器基本都支持但老浏览器需要 polyfill 或者降级 —— 正好这也是项目选型时需要考虑的点。最后他问了一个我完全没想到的问题“Vue 的 nextTick 原理是什么如果让你实现一个简易版你会怎么做”我在项目中用过 nextTick也知道它跟 DOM 更新后的回调有关但真正要我说原理就垮了。我只能说跟微任务有关然后就卡住了。面试官没太难为我告诉我核心是利用 Promise.then 或者 MutationObserver 把回调放进微任务队列等 DOM 更新后执行。这道题我后来认真补了绝对是 Vue 源码里最值得深入的一块因为它牵扯到事件循环、异步更新、组件渲染机制。4. 三面leader 面的终极问题不是技术是「思考」4.1 业务与技术的关系混子如何急中生智二面过后的第三面面试官已经明显是技术 leader 级别开场完全不问代码先问我“你在这个项目里有没有过跟产品经理或者后端发生分歧的时候你最后怎么处理的”这种问题对于混子来说是最容易翻车的因为平时我就是那个“行行行你说啥我做啥”的人。但这次我急中生智讲了一个真实但稍微润色过的故事之前有一次产品提了一个需求要求前端做大量数据的即时筛选和排序我预估了一下如果按需求直接实现页面会有明显卡顿于是我没有直接拒绝而是先做了一版 demo用一万条数据实测截了性能面板的图给产品看然后提出了虚拟滚动 服务端筛选的替代方案最终产品接受了。面试官接着问了一句特别有价值的话“你觉得自己在这个过程中除了开发还承担了什么角色”我说其实前端不只是把设计稿变成页面还需要充当技术方案和业务诉求之间的翻译官。这句话后来想想有点装但在当时居然赢得了面试官的点头。4.2 成长性问题你怎么学习、怎么复盘leader 面后半段偏“软素质”了。问题包括平时怎么学习前端的未来三年的规划是什么最近有没有关注什么前端新技术学习路线我是这么说的日常以项目为主遇到问题先查文档、再查 issue、最后翻源码业余会看一些前端社区的高质量文章重点关注工程化和性能优化方向偶尔会动手写点小 demo 来验证想法。面试官追问“那你最近看过印象最深的一篇文章是什么”我愣了一下临时想到前端工程化里的微前端方案说最近在研究微前端的沙箱机制。其实那篇文章我只看了半篇但为了圆场我硬是把 main 应用和子应用之间的样式隔离、js 沙箱概念讲了个大概。这轮的心得是不要给自己挖坑。面试官问你看过什么一定要挑一个你真的熟悉的技术不然他顺着你的回答连续追问下去你就会像我一样哑火。后来面试官真的追问了“沙箱是怎么实现 js 隔离的”我答得很虚只能说出 with Proxy 的 eval 方式因为他提了我就顺藤摸瓜说了两句属于运气比较好。4.3 反问环节别问没营养的问题三面最后留了几分钟反问面试官很客气地说“你有什么想问我的”。我之前看过不少面经知道反问环节不能回答“没有”但也不能问太浅的问题。我问了两个问题一个是“团队目前的前端技术栈和工程化建设到什么程度”另一个是“如果我有幸加入您觉得我当前最需要补足的能力是什么”。这两个问题的好处是第一表现出你对团队感兴趣第二能通过面试官的回答反推自己哪些方面弱即便没拿到 offer也是很有价值的反馈。面试官回答第二个问题时说了一句我印象很深的话“你基础不算差但学习方式偏零散如果你能把一个知识点吃透到能主动教会别人的程度会好很多。”这句话后来被我当成很长一段时间的座右铭也彻底改变了我刷前端面试题的方式。5. HR 面聊薪资与 offer 的博弈5.1 HR 面的套路不是聊天是谈判HR 面放在三轮技术面之后大概 30 分钟。很多人以为 HR 面就是聊聊天其实不是HR 面是有明确目的的她要知道你的期望薪资、最快到岗时间、手里的其他 offer、离职原因、稳定性、学历背景等每一项都可能影响定级和薪资。HR 第一个问题就是“为什么从上家公司离职”。我提前准备过没抱怨加班多、没说领导不好而是说“做了两年业务型前端觉得技术成长变慢了想换一个技术氛围更浓的平台”。这个答案既真实又不招黑。她接着问“目前手里有其他 offer 吗”。我当时其实手里只有一个中小厂的 offer薪资还没谈但我没有撒谎也没有把话说死就说“有一个在流程中的机会但更倾向于这边因为更想做技术深耕”。后来我复盘觉得这个回答还行既表明了竞争力也给对方留了空间。5.2 谈薪话术混子的不算技巧的技巧薪资环节是 HR 面最核心的部分。我因为上一家薪资不高所以在定期望值之前做了一点功课查了市场行情、问了一圈朋友最后报了一个比当前薪资高大概 25% 的数字留了 5% 的还价空间。HR 问“你期望薪资为什么是这个数”我说了三层逻辑第一基于当前市场行情和岗位要求这个区间在合理范围第二对比我现在的能力和项目经验能独立负责复杂模块第三如果定级和期望有差距也可以考虑其他综合福利和成长空间。整个过程没有硬刚但也没有一上来就自降身价。这里有个细节HR 问“能不能接受定级低一些”我说“如果定级对应的工作内容是我感兴趣的可以谈但薪资上希望尽量靠到某个区间”。这种“定级可以让步薪资不能太离谱”的回答方式既显得务实也给 HR 留下了协商空间。最后 offer 给的薪资虽然比期望少了 2K但综合下来比我上家涨了不少我接受了。6. 面后复盘混子进场带着什么离场6.1 面试中暴露的问题清单虽然最后拿到了口头 offer但我清楚这轮面经里我的表现不是“稳”而是“悬”。回看整个流程我暴露的问题非常典型也很有参考价值。手写代码基本功不扎实防抖、深拷贝、Promise.all 都属于高频题但我写得不快且不规范尤其 Promise.all 的实现顺序问题暴露了我对 Promise 内部机制的浅层理解。知识点碎片化不成体系flex-basis 默认值、nextTick 原理、宏任务微任务调度这些点单独问都能聊几句但一旦被追问“为什么”就卡壳。项目中的技术决策缺乏数据支撑分片大小为什么选 5MB、优化效果具体是多少我说不出来这是面试官最敏感的部分。学习方式偏被动leader 面问我看过什么文章我只记得大概是某个方向但没有真正消化成自己的知识结构。Vue 3 知识储备不足JD 里明确写了 Vue 3我只知道 Proxy 比 defineProperty 强但组合式 API 的底层设计逻辑、编译优化等内容基本空白。这些问题不是面试失败者的专属反而是很多“能干活但说不出来”的前端共通的短板。我把它列出来是想让大家明白混子不可怕可怕的是不知道自己混在哪。只要能定位到具体的能力缺口接下来补就是了。6.2 给下一批「混子」的4条实在建议结合我这次经历给同样准备大厂前端面试的同学几条建议第一把简历上的每一条项目经历都准备成一个 5 分钟的故事。故事要包含背景、难点、你的方案、踩过的坑、最终效果。这样面试官问什么你都能往这个故事上引不会出现“你做过什么”和“你会什么”两张皮的情况。第二手写题必须脱离背诵真正动笔跑一遍。我现在都记得 Promise.all 那道题给我带来的屈辱。建议把防抖、节流、深拷贝、Promise.all、Promise.race、数组扁平化、柯里化、new、call/apply/bind、instanceof、EventEmitter 这类高频手写题全部在本地跑过三遍以上直到闭上眼睛能写出来。第三建立一个“为什么”清单。每刷一道八股文就追问自己三次“为什么”。比如事件循环不仅要背宏任务微任务的顺序还要知道为什么要区分宏任务和微任务比如 Vue 响应式不仅要背 Proxy还要知道 Vue 2 为什么不用 Proxy。面试官最爱追问的点往往都在三次“为什么”之后。第四视频面试一定要录音。我面完之后回听录音才发现自己有大量的“嗯”“那个”“就是”这类停顿词而且很多题明明答到了关键点但因为表达不清晰听起来像没答到。录音复盘是成本最低、提升最明显的练习方式。6.3 复盘表格哪些题该拿分却没拿住我把整场面试的题目和自己的表现整理成了表格方便大家直观感受大厂面试的考察密度面试轮次核心题目我的表现丢分点得分点一面闭包与防抖手写中偏下防抖节流条件写反this 绑定不清能给出防抖的应用场景一面深拷贝手写偏下循环引用和特殊类型处理不当知道 JSON 方案的局限一面Promise.all 手写偏下结果顺序错误边界处理不全能写出基本框架一面浏览器缓存良好无明显丢分Cache-Control 字段和协商缓存优先级二面大文件分片上传中上分片大小的技术依据不足对哈希、秒传、并发控制有实践二面性能优化指标中缺少量化数据知道 LCP/FCP 的基本概念二面Vue 响应式原理中上nextTick 原理不清晰Vue2/Vue3 对比答得较完整三面业务分歧处理良好无明显丢分有实际案例表达清晰三面学习方式与技术趋势中技术文章印象不深微前端细节经不起追问能表达学习方向HR面期望薪资与稳定性良好无明显丢分谈薪有策略表达务实表格里能看出来我的优势在“有真实项目经历支撑的实战问题”劣势在“纯基础概念的深度和手写能力”。如果你也打算面大厂可以先自己模拟打一次分看自己到底属于哪类选手然后针对短板集中突破。回看整个面试过程我最大的感受是混子不混、只是平时没把知识形成体系。真正让我通过这轮面试的不是面试前那两周背了多少题而是过去两年在项目里踩坑时留下的肌肉记忆以及对项目细节的认真复盘。如果你也是一枚混子别慌把我踩过的坑避开把我侥幸过关的地方变成你的稳定项大厂的门没有想象中那么窄。最后再分享一个小技巧面试被问到不会的题别直接说“不会”试着说出你的思考路径比如“我对这个问题不了解但我从另外一个角度推测可能是……”。面试官要的不是满分答案而是看你遇到未知问题时的反应。这个能力恰恰是混子最容易被低估的地方。
返回列表