百度前端秋招笔试复盘:从JS原理到算法题型的备考指南 每年一到七八月份大厂秋招就陆续启动了。我去年参加了百度的前端岗秋招笔试整体感受是难度不算夸张但考察的覆盖面非常广从网络协议到浏览器原理从手写Promise到算法题几乎每个前端基础板块都会被点到。如果你今年准备投百度前端岗这篇复盘能帮你把笔试的考察方向、题型套路和备考重点一次性捋清楚。先说结论百度前端笔试的基调是“重视基础、偏向原理、算法有区分度”。它不像字节那样爱考工程化和场景设计也不像腾讯那么偏重计算机基础百度更像是“前端基础和算法能力都要但都不求最顶尖”。选择题里藏着大量细节坑编程题难度中等偏上能拉开差距的往往是边界条件的处理和对复杂度的优化意识。1. 笔试整体风格与考纲拆解笔试总共120分钟题量在45到50题之间题型分布大概是单选题25题左右多选题10题左右编程题2到3题。选择题覆盖计算机基础、网络、JavaScript、浏览器原理、前端框架编程题则以LeetCode中等题为主。我先说我印象最深的几点。第一多选题真的是用来拉分的因为少选、多选、选错都不给分很多选项描述得极像“正确答案”比如关于事件循环的某个说法措辞改了一个字就从对变错。第二编程题不是传统的ACM风格而是偏向“实现功能、处理边界”的工程向题目输入输出不会出特别刁钻的格式但要求你考虑空值、异常输入、大数据量性能。从考纲权重来看我把历年高频考点整理成了一个表方便你对照自身薄弱项做准备考察方向大概占比典型考点JavaScript核心25%事件循环、闭包、原型链、异步编程、数组方法计算机基础网络/操作系统20%HTTP缓存、TCP、DNS、进程线程、内存管理HTML/CSS10%盒模型、BFC、flex/grid、回流重绘数据结构和算法20%数组/链表/树、动态规划、字符串处理前端框架15%React/Vue生命周期、虚拟DOM、diff算法、组件通信工程化及其他10%Webpack原理、性能优化、安全XSS/CSRF这个分数分布是我个人的经验值每年的具体比例会波动但前端基础和算法这两块是永远的主旋律。我在准备时最明显的感觉是背框架API根本不够百度考的是“为什么这个框架要这样设计”。1.1 为什么百度笔试爱考基础原理百度前端面试向来有“手写源码”的传统笔试自然也会延续这个风格。笔试没法现场看你写代码的过程所以选择题就会变成“考原理”的重灾区。比如它会给你一段代码问你输出顺序是什么给你一个对象和一段操作问引用类型的值变化给你一个HTTP请求的时序图问缓存命中的是哪个阶段。我当时复习的切入点就是不背结论自己去推演一遍。把“闭包是什么”换成“闭包在这段代码里如何导致变量被意外保留”把“transform为什么比top性能好”换成“浏览器在合成阶段做了什么”。这样面对选择题的变化题才不会慌。1.2 和字节、腾讯笔试的横向对比每年秋招大家都会在几个大厂之间海投所以我顺手对比一下三家的笔试风格帮你制定差异化的复习策略。大厂笔试侧重点编程题风格百度前端基础、网络、原理细节中等偏经典偏逻辑和边界字节工程化、场景设计、手写偏实现题量偏大思路要快腾讯计算机基础、操作系统、网络算法题偏数据结构思路要全如果时间紧你自己要先定目标只冲百度就主攻基础细节同时准备多家就把算法的优先级提上来。因为算法是全国大厂笔试的通用的门槛先把力扣常考题型刷熟再去补各家的特色考题效率最高。2. 计算机基础与网络知识笔试第一大送分池很多人觉得前端不用太懂网络笔试里偏偏考得很多。百度的选择里TCP、HTTP、DNS、浏览器缓存几乎每年都出现。这些内容其实不难属于“只要你系统复习过就能拿分”的板块但问题恰恰在于大家平时写业务根本接触不到这些细节。2.1 TCP握手和缓存策略的经典考法关于TCP三次握手和四次挥手选择题常见的挖坑方式有两种一是问你握手阶段的状态变化二是问四次挥手时TIME_WAIT出现在哪一端、作用是什么。比如真题里这样出过“客户端发送FIN后首先进入什么状态”答案是FIN_WAIT_1很多人会误选成TIME_WAIT。这个知识点本身不难只要把状态迁移图完整过一遍就能记住。TIME_WAIT是在客户端收到服务器最终ACK之后才进入的目的是让迟到的报文段有时间被丢弃避免影响新连接。HTTP缓存这块百度喜欢结合具体场景出题。比如第一次请求返回了Cache-Control: max-age3600问10分钟后再发请求会走强缓存还是协商缓存或者给你两个响应头让你判断哪个优先级更高。实际上相关优先级是Cache-Control的no-store最高然后是no-cache、max-age最后才是Expires。如果还带上了ETag那么协商缓存阶段的判断顺序是先看Cache-Control是否过期过期后再带If-None-Match请求头服务器比对ETag决定返回200还是304。2.2 操作系统的进程线程与内存考点前端岗考操作系统不会出得太深但进程线程的区别、死锁产生的四个必要条件、虚拟内存和分页这些基础题命中率很高。比如它会给你四个场景让你判断哪个不会导致死锁“互斥条件、请求保持、不可剥夺、循环等待”这四个条件缺一不可少一个都不是死锁。这里我推荐用一句话串起来记忆死锁就是“每个人都占着碗里的、盯着锅里的又没人愿意放筷子”。这样遇到多选题问必要条件你只需要检查四个选项是否都具备即可。有意思的是百度笔试还考过一次“栈和堆的区别”乍一看以为是数据结构的题实际上它问的是内存分区。栈区由编译器自动分配释放存放函数参数、局部变量堆区由程序员分配释放比如new出来的对象。前端语言虽然不会让你手动管理内存但理解这个模型对面试中聊V8内存机制、垃圾回收也有帮助。3. JavaScript核心笔试的选择题重灾区如果说计算机基础是“背了就给分”那么JavaScript选择题就是“看了选项觉得自己会对答案发现自己错了一片”的板块。主要原因在于JS的隐式转换、异步机制、作用域规则细节太多每个选项都能编出一个判断点。3.1 事件循环与宏任务/微任务的必考套路几乎每年必考一道“代码输出顺序”题。初始代码大概是console.log(script start)、setTimeout、Promise.resolve().then、async/await、console.log(script end)让你输出执行顺序。这个题能把很多人绕晕的地方在于async函数内部的await后面那段代码其实相当于被放进了微任务队列。当时我踩过的一个坑是await后面的代码不一定是在当前Promise微任务里执行。拿这段代码举例async function test() { console.log(async start); await Promise.resolve(); console.log(async end); } console.log(sync); test(); setTimeout(() console.log(timeout), 0);输出顺序是sync、async start、async end、timeout。注意await Promise.resolve()右边表达式先执行Promise.resolve()已经resolved所以await会把后续代码作为微任务排队当同步代码执行完微任务队列里“async end”先跑再跑宏任务timeout。如果await后面跟的不是Promise而是一个普通值底层会把它包装成Promise.resolve(value)执行逻辑不变。这个知识点真的值得多刷几道变种题。比如把await语句放在for循环里await是顺序执行的不是并发。此时如果你想让多个异步请求并行就需要用Promise.all这也是面试官很喜欢追问的点。3.2 闭包、this指向与原型链的选择题陷阱百度的选择题特别喜欢把闭包和var/let声明混在一起考。有一段经典代码for (var i 0; i 5; i) { setTimeout(() console.log(i), 1000); }这段代码的坑在于var声明的i是函数作用域循环中创建的五个箭头函数共享同一个i等定时器触发时i已经变成5所以输出五个5。把var改成let后每次循环会创建一个块级绑定所以输出0、1、2、3、4。原理上就是闭包捕获了每次迭代的独立变量而不是最终的变量状态。this指向其实比闭包稍微好背一点因为规律是固定的普通函数的this取决于调用方式箭头函数的this取决于定义位置。但笔试题目往往不是考这个结论而是让在代码中间填入一段调用使得this指向某个对象。我当时总结的方法是做题先画出“调用现场”foo()挂在哪里、以什么形式被调用。是obj.foo()那this就是obj是独立调用那严格模式下就是undefined非严格模式是全局对象是new foo()那this就是新创建的对象。原型链题目则最爱考instanceof的底层逻辑。instanceof并不是看构造函数的身份而是检查构造函数的prototype对象是否在实例的原型链上。所以有个经典反直觉例子f instanceof Foo并不等于f是Foo生成的如果Foo.prototype被替换成另一个对象老实例和老构造函数之间就没有关系了。我笔试时遇到的是给几个对象关系问哪个表达式返回true这种题只要把原型链画出来基本秒解。3.3 手写Promise与防抖节流的实战思路百度笔试的选择题里偶尔会出现“哪段代码正确实现了XXX”这时候手写代码的思考方式就派上用场了。我记得有一题是要求选出正确的深拷贝实现选项有的是浅拷贝、有的是JSON序列化方式、还有的是递归但没处理循环引用。如果平时只是背代码不自己写过很难迅速判断每个选项的缺陷。我在准备阶段养成了一个习惯重要的手写题一定要自己默写而不是复制粘贴。防抖、节流、深拷贝、Promise.all、Promise.race、new的实现、call/apply/bind的实现这八个是必练的。默写的好处是能记住关键细节比如bind返回的函数如果被new调用this应该被忽略深拷贝需要用一个WeakMap来记录已经拷贝过的对象避免循环引用导致栈溢出。这里给出一个带循环引用处理的深拷贝模板笔试选择里经常考它的优化点function deepClone(target, map new WeakMap()) { if (typeof target ! object || target null) return target; if (map.has(target)) return map.get(target); const clone Array.isArray(target) ? [] : {}; map.set(target, clone); for (const key of Reflect.ownKeys(target)) { clone[key] deepClone(target[key], map); } return clone; }这道题里的关键点有两个一是WeakMap避免了循环引用和内存泄漏二是用Reflect.ownKeys可以遍历到Symbol类型的键。很多代码题表面上是在考函数实现实际上是在考你对语言底层特性的理解这一点在百度笔试体现得特别明显。4. 浏览器原理与网络请求前端面试高频场景浏览器原理这块百度考察的集中度很高基本上就是三件事从输入URL到页面渲染发生了什么、浏览器的缓存机制、回流重绘的触发条件与优化。第三个内容还经常和性能优化选择题绑定后面我会一起说。4.1 从URL输入到页面渲染的全过程这大概是前端面试最“八股”的题但笔试和面试考法不一样。笔试往往把其中某一步拆开变成判断题或者让你排序。步骤大体是DNS解析、建立TCP连接、发送HTTP请求、服务器响应、浏览器解析HTML构建DOM树、解析CSS构建CSSOM、合并渲染树、布局、绘制、合成。我见过一道真题选项里混入了“浏览器先解析JavaScript再解析CSS”的错误说法。事实上浏览器解析过程是分主线程和预加载扫描的CSS不会阻塞DOM解析但会阻塞渲染因为渲染树需要CSSOM。而带defer的script标签会延迟到整个文档解析完成后再执行async则是一旦下载完成就立即执行有可能Javascript先执行而阻塞DOM构建。遇到这种排序题我建议关键记两点渲染树只有可见元素display:none的节点不会出现在渲染树中visibility:hidden虽然不可见但仍会占据布局空间所以它仍然在渲染树中只是不绘制。这个区别经常被出成判断题。4.2 前端缓存、CDN与强缓存/协商缓存的区别缓存几乎属于必考题。强缓存相关的响应头是Cache-Control而不是Expires。Cache-Control的max-age优先级高于Expires后者是HTTP/1.0的产物经常被拿来做干扰项。协商缓存相关的头是ETag/If-None-Match和Last-Modified/If-Modified-Since其中ETag优先级更高因为HTTP/1.1中ETag比Last-Modified更准确。面试和笔试常考的一个场景题是“为什么说ETag比Last-Modified更可靠”因为Last-Modified只能精确到秒同一秒内文件修改了但时间没变客户端就会拿到旧缓存ETag则是服务端根据文件内容计算的唯一标识内容变了标识就变精确度更高。我在笔试中就遇到了这个考点只不过它用选项描述换了个说法让你判断哪种情况下必须用ETag。CDN的缓存策略也偶尔出现考点无非是Cache-Control: s-maxage与max-age的区别s-maxage只对CDN缓存生效而max-age对浏览器本地缓存生效。这个点如果在备考时没注意很容易选错因为它考得非常细。4.3 回流和重绘的优化方向回流和重绘的触发条件笔试喜欢用“下面哪个做法可以减少回流”来考。正确的方向包括批量修改DOM、使用class切换样式、避免频繁读取offset等布局属性、使用transform代替top/left动画等。这里我想提醒一个大家容易记错的点transform动画不会触发回流重绘而是直接进入合成阶段由GPU处理。但读offsetWidth会强制同步布局如果你在改完样式后立刻读它性能消耗最大。原因在于修改样式后浏览器需要重新计算布局但通常它会攒在一起批量处理当你立即读取布局属性时为了给你最新的值浏览器不得不立刻执行一次布局计算这样之前攒着的修改就失去了批处理的意义。笔试中碰到了与Performance相关的选择题就考了这一点。我当时把常见的触发回流的操作整理成了一个清单增删DOM元素、修改盒模型属性width、height、margin、padding、修改定位属性、读取offsetWidth/scrollWidth/getBoundingClientRect等。优化方向归纳为三个减少次数、减少范围、避免强制同步。5. 前端框架与工程化框架题不只是背API百度笔试的框架题特点很鲜明不会让你写一段React组件也不会让你记住Hooks的用法列表而是考框架底层的原理和设计思想。比如虚拟DOM的diff算法、key的作用、useEffect的依赖机制、Vue3响应式与Vue2的区别。5.1 React虚拟DOM与diff算法考点虚拟DOM在笔试中最常见的考法是虚拟DOM是什么它比直接操作DOM快吗这里有一个经典的“坑”虚拟DOM并不总是比原生DOM操作更快。它真正的价值在于把“命令式操作DOM”变成了“声明式描述UI”让框架可以在数据变化时批量计算最终需要变更的DOM节点减少不必要的操作同时提供跨平台能力。diff算法考点里key的作用占据了核心位置。列表渲染时使用key可以帮助React识别哪些元素发生了改变、新增或删除。但这里要强调一点key不是用来提升渲染性能的正确使用key可以减少节点复用时的重复渲染但如果key乱用比如用数组索引当key在列表顺序变化时反而会造成状态错乱。有一年笔试考了“列表项中间插入一条数据使用index作为key会有什么问题”答案是项的状态可能会被复用导致输入框内容错乱。5.2 Vue3响应式原理与Vue2的差异Vue3的响应式是面试高频点笔试常考它和Vue2的差异。Vue2使用Object.definePropertyVue3使用Proxy。两者最核心的区别在于defineProperty只能拦截对象属性的读取和赋值无法拦截属性的新增、删除、数组索引变化Proxy可以拦截整个对象的13种操作包括in操作符、delete、ownKeys等所以Vue3能够做到“新增属性也是响应式的”。多选题曾经问过Vue3Ref和reactive的区别。Ref包装的是基本类型值也可以包装对象但访问时要通过.valueReactive只能接收对象访问时直接obj.xxx。这里有个记忆技巧Ref的本质是创建一个RefImpl实例内部用reactive对象的value来存储实际数据所以Ref包装对象时修改obj.value.name同样能触发更新。5.3 Webpack、Vite与前端性能优化工程化题不会让你手写配置但会考概念。比如Tree Shaking依赖ES Module的静态结构因此import { a } from ./module可以被摇树而CommonJS的require(./module)不行。再比如懒加载借助动态import()实际是在构建时把单独的代码块拆成一个chunk运行时按需加载减少首屏包体积。Vite高频考的是它的开发模式为什么快Vite利用浏览器原生ES Module按需加载源文件而不是像Webpack那样先打包完再启动服务。所以项目大了之后Webpack冷启动可能要几十秒Vite基本秒开。这个对比几乎每次都会出现建议特意记一下“依赖预构建”用esbuild和“源码按需编译”这两个关键术语。性能优化题相对比较综合不局限于工程化。我遇到的是一道图片加载场景题首屏图片用CDN WebP 懒加载字体文件用font-display: swap。如果只从工程角度回答方向就是拆包、压缩、缓存、边缘计算这一套。6. 算法与编程题拉开差距的核心战场百度笔试的编程题一般是2到3题其中一题简单偏中等另一题中等偏难如果只有两题那第二题多半带一点DP或贪心味道。这里不要求你AC全部测试用例但通过的测试用例比例直接影响面试官对你的初始评价所以尽量把能想到的边界都处理好。6.1 真题风格复盘中等偏经典逻辑要严密秋招阶段大家会刷力扣我的经验是刷题不必追求“死磕Hard”把高频题型的模板和套路搞清楚更关键。比如最长无重复子串、二叉树层序遍历、LRU缓存、三数之和、接雨水这五道题几乎覆盖了滑动窗口、BFS、哈希表、双指针、单调栈等核心思想。我那次遇到的一道编程题是“给定两个字符串形式的数字返回它们相乘的结果不能用BigInt”这题本质上考大数乘法需要模拟竖式。核心思路是用一个数组先按位相乘累加再统一处理进位最后把前导零去掉。仔细敲完代码通过率能到90%以上剩下的就是处理边界如果两个字符串里有一个是0直接返回0。另一道题是二叉树相关要求判断一棵树是不是对称二叉树。最简单清晰的解法是递归判断左右子树左子树的左孩子等于右子树的右孩子左子树的右孩子等于右子树的左孩子这个对称关系很直观。这道题在LeetCode上是Easy放在笔试里属于送分题但很多人在递归终止条件上出了问题只判断了节点是否为空忘了判断值是否相等导致错误。6.2 输入输出处理和边界条件的经验在线编程环境用的是赛码网输入输出格式和力扣不同。如果平时只写函数不练全流程考场上很容易卡在输入读取上。我当时提前熟悉了readline的用法const readline require(readline); const rl readline.createInterface({ input: process.stdin, output: process.stdout }); rl.on(line, (line) { const nums line.trim().split( ).map(Number); console.log(solve(nums)); });编程题里最常见的三个坑我一一踩过第一个是字符串输入里混了多余空格最稳妥的办法是先用trim()去掉两端空白再split。第二个是输出格式要求末尾不能有多余空格可以用数组收集结果后join( )再统一输出。第三个是Number类型在超大整数相乘时精度丢失但题目又偏偏让你处理超过Number.MAX_SAFE_INTEGER的数这时候要么用字符串模拟要么用BigInt我个人建议字符串模拟更保险因为部分评测机对BigInt的支持和性能并不稳定。6.3 值得提前刷的题型清单结合百度的出题偏好和我自己在牛客上刷面经整理的规律以下题型优先级最高题型代表题考察点哈希表两数之和、最长无重复子串空间换时间链表反转链表、判断环路指针操作、快慢指针二叉树层序遍历、最近公共祖先BFS、递归动态规划爬楼梯、最长递增子序列状态定义、转移方程字符串大数相加/相乘、回文判断模拟、边界老生常谈但还是要强调刷题别贪多每道题做完最好把思路在注释里写清楚否则过两周回来跟没做过一样。我习惯用“三遍法”第一遍自己AC第二遍隔天看题直接讲思路第三遍重新手写代码不看答案。这样刷下来中等题基本能形成条件反射。7. 笔试环境与答题策略细节决定成败很多人只关注知识复习忽略了笔试环境本身的影响。在线笔试和本地IDE差别很大某些细节如果没有提前适应考场上会白白丢分。7.1 赛码笔试环境需要提前熟悉的操作赛码网的编辑器不带自动保存切换题目时会有弹窗提示但如果你在最后几分钟还在改代码很容易因为切题导致未提交。我的建议是每做完一道题第一时间点保存并提交后续再做题就默认这道题已有提交记录心里踏实很多。第二点是代码编辑器支持本地调试和运行示例但只支持单文件调试如果你在代码里粘贴了多个函数又没调用运行结果可能不符合预期。所以试卷里的编程题最好按题号拆成独立文件不要把所有题的代码堆在一起。我还发现赛码网对Node.js的版本支持在特定年份有差异比如某些版本不支持ES Module的import语法。所以我写在线笔试代码时尽量用CommonJS的require/ module.exports避免因为环境语法报错而空耗时间。7.2 120分钟的时间分配策略我的时间安排是前40分钟做完全部选择题剩下的时间全部给编程题。选择题中遇到犹豫超过一分钟的题先标记跳过最后再回来看。这样做有两个好处一是优先拿到确定性的分数二是避免在一道选择题上纠缠太久导致后面编程题没时间写。编程题我建议按“先易后难、先保底后拔高”的策略。如果第一题简单直接写完并测试完整用例第二题如果中等偏难先写出暴力解并保证通过案例再考虑优化要是完全没思路那就把基础的输入处理和题目示例跑通至少保证没人空着交卷。7.3 选择题的涂卡式策略与多选题的得分技巧多选题宁可少选不要多选。百度笔试规定选错不得分但少选往往还有部分分数所以不确定的选项坚决不选。当时我有个多选题考的是HTTP状态码的语义选项里有“301永久重定向、302临时重定向、304未修改、404未找到”其中304让我犹豫因为304在语义上其实属于重定向类但它不同于301/302它是服务端验证缓存后返回“未修改”。如果我没有提前搞清楚“304和重定向的关系”很容易多选一个或者漏选一个。单选题如果遇到彻底不会的我用的是排除法加语义推断。前端技术名词大多有一定语义比如“BFC”“层叠上下文”“CSS包含块”看到含义能与题目背景吻合的选项优先选它。这种策略不是万能但至少比纯蒙的正确率高不少。8. 错题复盘与备考建议把笔试变成面试的跳板笔试之后不要急着对完答案就完事它是一个很好的查漏补缺工具。我对完答案后会做一个错题清单每个错题都标注三件事错误原因、对应知识点、参考资源。这样在准备下一家笔试或者面试时直接看清单就能快速进入状态。8.1 如何系统整理错题我用的模板大概是这样的表格每考完一家就更新一个Sheet题目关键词我的答案正确答案知识点归属错因分析instanceof 原型链ACJS原型链对Foo.prototype替换后行为不熟Cache-Control no-cacheBAHTTP缓存混淆no-cache与no-store错因分析一定要具体。不要写“基础不牢”这种废话要写“我误以为no-cache是不使用缓存实际是使用前需要协商验证”这样下次翻看才能触发记忆。8.2 时间紧的话重点复习哪些内容如果你距离笔试只剩两周我建议按权重分配JavaScript核心占四天网络和浏览器占三天框架原理占两天算法占三天剩下两天用于做真题模拟和错题复盘。JavaScript和算法是性价比最高的两块短期内能显著提升正确率。关于刷题量我的体感是力扣保持在150题左右其中简单30题、中等100题、困难20题覆盖面就已经够了。比多刷更重要的是保持手感我考试前一周每天固定做3道中等题雷打不动让大脑在固定时段进入算法状态。8.3 笔试复盘如何为面试铺路笔试中遇到的选择题很多都会变成面试时的追问话题。比如笔试考了“async/await和Promise的关系”面试官就可能让你手写一个支持超时和重试的请求函数。我当时就是靠笔试复盘把事件循环、Promise、缓存这几个点揉在一起吃透的后来面试被问到“如何设计一个带缓存Promise的请求函数”时直接答出了几个关键优化点面试官明显比较满意。我的建议是笔试结束后挑三个最薄弱的知识点自己讲一遍讲不通就再查资料。这个过程相当于在提前准备面试题一举两得。笔试本身不决定最终Offer很多人的笔试成绩只是“通过线”面试表现才是真正的分水岭。但从笔试中暴露出的知识盲区如果用心补上面试时就会变成你的加分项。这是秋招备考中我觉得最值得投入精力的部分。