百度前端校招笔试卷解析:核心考点与手写题实战攻略
2026/9/19 7:07:29 网站建设 项目流程

百度2019校招Web前端工程师笔试卷(第一批),这个名字一看就是奔着大厂校招去的。我当年也刷过不少类似的卷子,现在回头看,这类笔试卷考察的核心其实很稳定:基础扎不扎实、动手能力强不强、遇到问题有没有清晰的排查思路。Web前端岗位这些年变化很快,框架换了一茬又一茬,但校招笔试的风格反而一直很朴素,不会问你“用过什么最新特性”,更多是拿几道基础题和手写题,看看你代码功底到底怎么样。

这篇文章我打算围绕这套笔试卷展开,从考察逻辑、考点拆解、答题思路到备考方法,完整梳理一遍。不管你是正在准备校招,还是已经工作几年想查漏补缺,这篇内容都会对你有用。我不会只讲“这道题怎么做”,而是尽量讲清楚“为什么这么考”“背后的原理是什么”“还有哪些同类变体”,这样你换一套卷子也能应对。

1. 这套笔试卷在考察什么:从题目结构看大厂选人逻辑

1.1 整体题型分布与考察目标

百度2019校招前端的笔试卷(第一批),题型上跟当时大多数一线互联网公司保持了一致的风格:选择题(含单选和多选)、简答题、手写代码题混合。选择题覆盖的面很宽,从HTML标签语义、CSS布局特性到JavaScript运行机制、浏览器原理都有;简答题则偏重概念解释和场景分析;手写代码题是区分度最高的部分,往往直接决定你能不能进入下一轮面试。

这份卷子最难能可贵的一点是,它并不追新。2019年的时候Vue和React已经非常流行了,TypeScript也在升温,但卷子里的重点仍然放在原生JavaScript上,框架相关的内容占比不高。这说明出题人的核心思路是:框架可以入职后学,但语言功底和计算机基础短期内补不出来。这一逻辑到今天依然成立,现在的校招笔试虽然增加了工程化、Node相关题目,但底层考察点从来没变过。

1.2 为什么这些考点被反复翻牌

大家如果有印象,前端面试题里翻来覆去就是那些:闭包、原型链、事件循环、跨域、性能优化。有人觉得烦,说“工作中根本用不到闭包啊”,但笔试考这些不是没有道理的。

举个例子,闭包表面上是“函数嵌套函数、内部函数引用外部变量”的语法现象,但真正理解闭包,意味着你理解作用域链、变量生命周期、内存回收。这些概念直接关系到代码里会不会出现意外共享状态、内存泄漏、回调函数里this丢失等线上问题。原型链更是JavaScript面向对象的基础,组件化开发中继承、方法复用的实现都离不开它。事件循环则决定了代码执行的顺序,尤其在前端异步场景爆炸的今天,一套交互里全是Promise、setTimeout、requestAnimationFrame,不理解事件循环,调试都会一头雾水。

所以说,笔试题目看起来“基础”,实际上是在用最少的题目探测你的计算机功底和思维方式。这是大厂选人成本最低、效率最高的一种方式。

2. 核心考点详细拆解:拿到题目后应该怎么想

2.1 HTML与CSS:布局实战与细节陷阱

HTML和CSS在笔试中通常不会太难,但题目的坑往往藏在细节里。盒模型是必考项,标准盒模型(box-sizing: content-box)和IE盒模型(border-box)的区别要能直接说清楚,padding和border到底算不算在width内,这是写布局的第一步。

CSS布局的考察一般集中在三块:居中方案、两栏/三栏布局、BFC清除浮动。居中问题经常以选择题形式出现,问“下列哪个方案能实现水平和垂直居中”,选项里可能有margin: auto、flex、绝对定位加transform、line-height等,平时每种方案都要自己敲一遍,考试才不会掉坑。比如flex布局的justify-content: center和align-items: center组合,只有容器有确定高度时垂直居中才有效,如果容器高度塌陷,这个方案就失效了。

笔试里如果有手写CSS的题,建议按“从低版本兼容到高版本”的思路作答。比如实现三栏布局,可以先写浮动,再写flex,最后补充grid,同时把各自的适用场景和兼容性问题写清楚,这样能体现你的方案意识,而不只是会背代码。清除浮动的方式也要准备一套标准答案:父级overflow: hidden、伪元素clear: both、父级也浮动等,每个方案的触发条件和缺点都要说清楚。

2.2 JavaScript基础考点:原型、作用域与this指向

JavaScript是笔试的重头戏,百度这份卷子里JS题目占比非常高。选择题里常考的是类型判断、作用域、this指向,手写题则偏向数组方法、防抖节流、深浅拷贝这类工具函数的实现。

先说this指向。这个知识点看似简单,但每一道题都能变形。核心规律只有一条:this的指向取决于函数被调用时的方式,而不是定义时的位置。普通函数调用,this指向全局(严格模式下是undefined);对象方法调用,this指向该对象;构造函数调用,this指向新创建的实例;箭头函数没有自己的this,它捕获定义时外层作用域的this。笔试里最常见的变形是“取出对象方法再单独调用”,很多同学看到这样的代码直接懵,其实只要记住“谁调用,this指向谁”,再落到具体代码上分析一遍就能解决。

原型链的考察通常不会让你画整条链,而是给一段代码问“输出什么”。比如定义一个构造函数,在prototype上挂方法,再new两个实例,其中一个加了自有属性,让你判断属性访问结果。这类题目建议先画出原型链,再逐个属性往上找,养成这个习惯后基本不会出错。

2.3 异步编程与事件循环:从看代码到写代码

事件循环类的题,百度的卷子里几乎每年都有。常考形式是给出一段混着setTimeout、Promise、async/await的代码,让你说出输出顺序。这类题想拿分,必须把浏览器的执行模型吃透:同步代码先执行,遇到微任务(Promise.then、queueMicrotask)放进微任务队列,遇到宏任务(setTimeout、setInterval)放进宏任务队列;当前宏任务执行完,清空整个微任务队列,再取出下一个宏任务,循环往复。

记一个简单版本:同一轮事件循环里,微任务永远比宏任务先执行。async/await本质上是Promise的语法糖,await后面的代码相当于被包进了then回调里,所以它也是微任务。笔试里面最常出错的点就是:明明先写了setTimeout,后写了Promise,结果Promise先输出。原因就在于Promise属于微任务,即使代码写在前面,也得等当前宏任务结束后统一执行。

如果卷子里有手写异步代码,常见的是手写Promise.all、手写带并发限制的请求池等。这类题我要单独拎出来讲,因为它们是笔试手写题里性价比最高的准备方向。

3. 框架与工程化考察:不追新但要懂原理

3.1 框架考点:生命周期和响应式原理

2019年前后面试的时候,React和Vue已经占据主导,笔试里也会涉及框架题目,但不会太深。Vue的考察重点是响应式原理和生命周期。响应式原理要能说清楚Object.defineProperty如何拦截数据读写、每个组件实例的Watcher如何收集依赖、数据变化后如何通知视图更新。同时也要知道Vue 3的Proxy是怎么实现的,以及它解决了defineProperty数组和新增属性监听的问题。

React的考点则集中在setState的批处理机制、生命周期(尤其是旧版componentWillMount到新版getDerivedStateFromProps的变化)、虚拟DOM和diff算法。很多人会背“key的作用是优化diff”,但笔试如果让你具体说“diff算法怎么对比新旧节点”,很多人就卡住了。这里的关键是:同层对比、类型不同直接替换、类型相同只更新属性、列表通过key来复用。其实不需要把源码背下来,把这三个原则用白话讲清楚,再把key的作用结合场景说透,就能拿不错的分数。

3.2 工程化与浏览器原理:性能题背后的知识体系

工程化相关的笔试题目这几年越来越多。Webpack的考察点集中在:loader和plugin的区别、构建流程、打包优化手段(代码分割、Tree Shaking、缓存)。这类题想答好,最好真的去配过一遍Webpack,因为很多说法只有配过才知道怎么回事。比如Tree Shaking生效的前提是模块使用ES Module语法且没有副作用,这个条件在commonjs时代是不具备的。

浏览器相关的题目也值得重视。渲染过程的基本链路是:解析HTML生成DOM树、解析CSS生成CSSOM树、合并成渲染树、布局(Layout)、绘制(Paint)、合成(Composite)。性能优化的题目就是从这条链路往下展开的:减少重排重绘、使用CSS动画代替JS操作DOM、图片懒加载、路由懒加载、代码分割、CDN加速、HTTP缓存。答这类题目要注意分点、有逻辑,最好结合“用户可感知的加载指标”(FCP、LCP、CLS)来讲,会让你的答案更显专业。

4. 实操过程与核心环节实现:两道手写题的完整解题思路

4.1 手写防抖函数(debounce)

防抖是笔试题里出现频率最高的手写题之一,百度的卷子里也经常出变形,比如“实现一个带立即执行选项的防抖函数”。别小看这道题,能一次写对的人并不多。

先明确防抖的核心思路:事件触发后,等待N秒再执行回调;如果N秒内再次触发,就重新计时。最基础的版本十行以内就能写完:

function debounce(fn, wait) { let timer = null; return function(...args) { if (timer) clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, args); timer = null; }, wait); }; }

这里有几个关键点必须说明。第一,timer需要存在闭包里,否则每次调用都会被重新初始化为null,防抖就失效了。第二,回调函数里用fn.apply(this, args)而不是直接fn(args),是为了保证事件处理函数内部的this指向正确,比如在Vue组件里作为方法使用时,this要指向组件实例。第三,返回的函数必须是普通函数而不是箭头函数,否则this会被绑定到定义时的外层作用域。

笔试如果让你“加一个立即执行选项”,思路也不难。加一个immediate参数,如果为true,则第一次触发时立即执行,后续触发在等待期内不执行,等待期结束后重新开放。实现时要维护一个记录“是否已执行过”的状态:

function debounce(fn, wait, immediate) { 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); }; }

注意这里必须把timer重新置为null,因为timer不单单是计时器句柄,它还充当了“是否处于等待期”的状态标记。这道题能把这个细节写清楚,基本就是满分答案。

4.2 手写instanceof实现

instanceof也是笔试常客。常规考察方式是问“instanceof的原理是什么”,进阶版是让你手写一个。它的核心逻辑是:检测某个对象是否出现在另一个构造函数的原型链上。

function myInstanceof(left, right) { let proto = Object.getPrototypeOf(left); const prototype = right.prototype; while (proto) { if (proto === prototype) return true; proto = Object.getPrototypeOf(proto); } return false; }

这里有两个要注意的边界。一个是left必须是非空对象(或函数),如果left是基本类型,直接返回false;另一个是right必须是函数,否则拿right.prototype会报错。笔试场上可以先把这两个判断加上,再写主体逻辑,代码显得更严谨。另外,如果能顺手提一句“Symbol.hasInstance可以自定义instanceof的行为”,会让面试官觉得你对JS的元编程也有了解,是加分项。

4.3 手写深拷贝:面试中最容易暴露问题的一道题

深拷贝是另一个高频手写题。很多人上来就写JSON.parse(JSON.stringify(obj)),这个答案如果作为简答题可以拿一部分分,但作为手写题基本要被扣分,因为它丢失了undefined、函数、Symbol、循环引用等场景。一个能覆盖大部分场景的深拷贝函数,大约需要二十行:

function deepClone(target, map = new WeakMap()) { if (target === null || typeof target !== 'object') return target; if (target instanceof Date) return new Date(target); if (target instanceof RegExp) return new RegExp(target.source, target.flags); if (map.has(target)) return map.get(target); const clone = Array.isArray(target) ? [] : {}; map.set(target, clone); Reflect.ownKeys(target).forEach(key => { clone[key] = deepClone(target[key], map); }); return clone; }

循环引用的问题必须处理,不处理就会栈溢出。这里用WeakMap存储“原对象到克隆对象”的映射关系,遇到循环引用时直接返回已经克隆过的对象。为什么用WeakMap不用Map?因为WeakMap是弱引用,不会阻止垃圾回收,在原对象被回收后,WeakMap里的键值对也会被自动清理,不会造成内存泄漏。这道题如果能把“为什么不直接用Map”这个点说出来,面试官通常都会眼前一亮。

5. 笔试实战中的常见问题与排查经验

5.1 选择题丢分的心理误区

很多人在选择题上丢分不是因为不会,而是因为读题太急。前端笔试题里,选择题经常会在题干里埋“坑”。举个例子,问“下列哪种方式能解决跨域问题”,选项里同时出现“CORS”和“JSONP”,好像都是对的,但题目可能限定条件是“只支持GET请求的场景”,那答案就变成了JSONP。再比如CSS题里,四个选项都是实现居中的方案,但题目问的是“在不改变DOM结构的情况下”,那flex方案就废了。

我的建议是:选择题先划关键词,再来看选项,尤其是碰到“正确的是”“不正确的是”“优先使用的是”这些词,一定要放慢速度。多选题丢分更加可惜,很多知识点你其实知道,只是没注意到选项里的“不一定”“都”“必须”这类绝对化表述。遇到这种词,默认先数一遍它是不是真的成立,多数情况下绝对化选项都是有条件的。

5.2 手写题的排错思路与时间分配

手写代码题最大的痛点是:思路明明正确,但代码一跑就报错。这通常集中在几个问题上:分号缺失导致语法解析错误、变量名拼写不一致、函数参数漏传、this指向发生变化。笔试题的代码量不大,报错之后先按这几个方向排查,比干瞪眼有效得多。

时间是笔试里最容易失控的资源。一份卷子七八十道题,如果每道选择题都纠结,到手写题的时候心态已经崩了。我的习惯是:选择题先快速过一遍,能确定的直接选,不确定的标记一下,最后统一回头看;手写题先审清楚题目要求,再打个草稿理思路,最后写到答题区域。手写题里如果有“实现一个XXX函数”的题,尽量给出完整可运行的版本,哪怕多写几行边界判断,也比只写一个空壳框架强。因为阅卷人看的是你的工程习惯,边界处理能力是校招场上很关键的分水岭。

5.3 复盘是提升最快的方式

每次刷完一套卷子,不要只看分数,更该做的是把每一道错题都拆开,找出错因。比如这道题错在“不知道这个API”,那就在知识树上补上这一点;如果错在“知道这个API但用错了场景”,就该想一想它和相似API的边界在哪里。我习惯准备一个错题文档,按“HTML/CSS、JS基础、异步、框架、网络、工程化”分类记录,并标注错误类型:概念不清、记忆模糊、粗心、场景不熟。这样考前翻一遍错题文档,效率比重新刷十套卷子还要高。

6. 从这份笔试卷反推出来的备考策略

6.1 复习优先级排序

如果你现在距离校招还有两到三个月,建议按“核心基础、计算机基础、框架原理、工程化工具”的顺序安排时间。JS的原生知识点一定是第一优先级,因为无论哪一场笔试,手写题都集中在JS上,而且这些题没有办法临时抱佛脚,只能靠反复练习。

CSS的复习策略是“重布局、轻特技”。Flex、Grid、定位、浮动、BFC这些高频考点要熟练掌握,而冷门选择器、生僻属性了解即可。计算机网络是容易被忽视的一块,尤其是HTTP缓存、HTTP/HTTPS、TCP三次握手、跨域解决方案,这些在笔试里的出现率非常高。数据结构与算法方面,数组、字符串、链表相关的简单到中等难度题目一定要刷到位,尤其是排序、去重、两数之和这类经典题,基本是每场笔试都会碰到的。

6.2 手写题怎么练才有效

手写题最怕“眼睛会了,手不会”。看十遍答案,不如自己在编辑器里敲一遍。建议每天挑两到三个高频手写题,关掉题解,从零开始写,写完再对照标准答案看差异。重点关注的是边界条件的处理,比如空值、参数顺序、隐式类型转换这些容易忽略的地方。

还有一个小技巧:不要只用一个方式实现。比如防抖,先写基础版,再写带立即执行版,再想想能不能用箭头函数改一版,最后再想想“如果需求变成节流,代码要改哪里”。这样你学会的不是一道题,而是一类题。笔试里的手写题从来不会原封不动地照搬题库,更多是微调需求,你掌握的是变化的规律,而不是静态的答案。

6.3 笔试之外的功夫:把知识点串成体系

这是我特别想强调的一点。备考笔试不应该是孤立的刷题,而是借刷题的机会完善自己的知识体系。比如你刷到一道关于“浏览器缓存”的题,不要只记“强缓存返回200 from cache,协商缓存返回304”,而是把整个链路串起来:浏览器发起请求、命中强缓存直接读本地、未命中则带上缓存标识去服务器、服务器返回304或200、响应头里的Cache-Control和ETag如何配合。如果这个链路你脑中是有画面的,无论题目怎么变形都不会怕。

同样,遇到“跨域”这个考点,可以串出三个层次:为什么会有跨域、常用的解决方案有哪些(JSONP、CORS、代理)、每个方案的原理和局限分别是什么。把知识点织成网之后,你不仅答笔试更稳,后续面试环节也会明显有底气。

7. 纸上谈兵没用:考场上的实操节奏与注意事项

7.1 拿到试卷前五分钟应该做什么

很多同学上考场第一件事就是埋头做题,这其实不是最优解。我的建议是先花两到三分钟把整张试卷浏览一遍,看清楚总题量、题型分布、以及手写题具体有几道。这样做有两个好处:一是能根据题目难度分配时间,二是能提前发现哪些题是自己薄弱的,做到心中有数。

比如你发现手写题有三道,其中有一道是“实现一个带并发限制的异步请求池”,这道题你不太熟悉,那就应该在选择题上加快速度,给手写题预留更多时间。相反,如果你发现选择题里有一半都是计算机网络题,而你刚复习过,那就可以轻松一些,把省出来的时间留给后面的难题。

7.2 答题区域的表达方式:代码排版和注释

手写题不是只给代码就能稳拿分,写在答题区域的代码能不能让阅卷人快速看懂,也很重要。建议遵循几个基本规范:函数名和变量名要有语义;关键逻辑加上一句注释;代码缩进保持一致;每个函数之间留出空行。不要小看这些细节,手写题阅卷通常很快,一个结构清晰、注释得当的答案,跟一份混乱的代码,给阅卷人的印象是完全不同的。

如果你是先在草稿纸上推演再誊写,那就更要注意:誊写的时候别漏行,尤其是return语句。手写题最可惜的失分方式就是逻辑全对,但代码因为少了一个return或者一个括号而变成死代码。

7.3 遇到不会做的题,别直接放弃

笔试过程中一定会遇到一两道完全没思路的题。这种情况最忌讳的是空着不写。哪怕是简答题,你也可以把自己知道的相关概念往上靠,把思考过程写出来。阅卷人给分的时候,通常会判断你是否具备“可培养的潜力”,而不是要求你每个知识点都掌握。一道“手写Promise.all”的题,如果你完整写出了Promise基本用法和all的语义,但没写出并发处理的细节,也能拿到一部分过程分。

对于选择题,如果确实不会,可以先用排除法去掉明显错误的选项,再在剩余选项里用“最不违背常识”原则做判断。但这些都是下策,最好的策略永远是考前把高频考点啃透,让“不会做”的概率降到最低。

8. 最后再分享一点实战经验

刷完百度这套笔试卷以及同期的其他大厂题目之后,我最大的体会是:前端校招笔试拼的不是天赋,而是信息差和熟练度。信息差指的是你知不知道考点大概有哪些、范围在哪里;熟练度则是你面对一道题能不能在短时间内给出结构完整的答案。这两样东西,都可以通过有针对性的刷题和总结快速提升。

备考期间我坚持做的一件小事,是把每次手写题遇到的边界条件单独整理到一个文档里。比如“防抖函数里timer = null 放在哪一步”“深拷贝里WeakMap存的是哪个方向”“instanceof第一个参数传基本类型会怎样”。这道题看着琐碎,但考试的时候发现,很多丢分点恰恰就是这些细节。你平时记录得越细,考场上的错误就越少。

如果你现在正处在校招备考阶段,别慌,按部就班地把JS基础、CSS布局、网络协议、算法基础这四块夯实,再配合高频手写题的反复练习,百度这套卷子的题型基本都能拿下来。更重要的是,你在准备过程中建立起的知识体系,会陪伴你走过后续的每一轮面试,甚至入职后的前几年都一直在受益。这就是我想说的:笔试只是关卡,真正值钱的是你为了过关而积累下来的能力。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询