ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

百度前端笔试真题解析:事件循环、HTTP缓存与CSS核心考点

百度前端笔试真题解析:事件循环、HTTP缓存与CSS核心考点 百度2019校招Web前端工程师笔试卷第三批。这份卷子在当年秋招季流传得相当广我前后研究过好几遍。做Web前端开发十几年我每年都会帮身边应届的朋友看看大厂笔试题实话实说百度这套题在当年不算最难的但信息量很足考点覆盖非常有代表性——JavaScript基础、浏览器原理、网络协议、CSS布局、手写代码全都在里面了。别误会我不是让大家去背题。校招笔试年年翻新但出题人背后的筛选逻辑变化很慢百度这种体量的公司招前端不是要一个只会写页面的人而是要一个懂浏览器渲染、懂HTTP缓存、懂事件循环、能在工程里独立定位和解决复杂问题的人。这份试卷恰恰把这个标准暴露得很充分。本篇文章围绕这份试卷涉及的六大知识模块展开整体考点布局、JavaScript异步与原型链、浏览器渲染与HTTP缓存、CSS布局陷阱、算法与手写代码、以及最后我个人的应试策略与复盘经验。文章里的代码、原理、避坑点都是可以直接拿来用的读完比你盲目刷十几套题要高效得多。适合两类人正在准备秋招春招的应届生以及工作两三年想跳槽检验基础是否扎实的初级前端工程师。1. 整体试卷印象与考点分布1.1 从试卷看百度前端选拔的核心逻辑把这份试卷完整过一遍你会发现一个很明显的特点几乎每一个知识点都不是在考你知不知道而是在考你能不能讲清楚为什么。比如CSS里问你BFC块级格式化上下文是什么不是让你背定义而是给了你一段实际布局代码让你判断为什么会有高度塌陷、怎么解决再比如问你HTTP缓存不是让你列几个字段名而是给你一个实际请求链路让你分析命中强缓存还是协商缓存。这种出题思路背后是百度前端团队对工程师的真实期待。大厂的前端岗位日常工作绝不是照着设计稿切图那么简单而是要面对复杂的业务场景首屏加载优化、组件库设计、Node中间层、性能监控、跨端方案。这些工作的底层全部依赖对JavaScript运行机制、浏览器工作原理、网络协议栈的深入理解。所以笔试筛选的从来不是背了多少面试题的人而是有没有建立完整前端知识体系的人。我见过不少候选人简历上写了一大堆Vue和React项目结果问他new Vue之后发生了什么答不上来问他为什么React的setState不一定是同步的一脸茫然。这类候选人在这份试卷上拿不到高分因为试卷考察的是底层原理而非框架API。反过来如果一个人能把事件循环讲透、能把原型链画明白、能手写一个Promise那即使框架经验少一点也大概率能通过笔试——因为这份试卷默认框架是可以在工作中速成的而基础必须提前打好。1.2 三类题型与时间分配的底层逻辑从题型结构看这份试卷大致分三类选择题/判断题、简答题、手写编程题。这三种题型考察的能力维度完全不同。选择题侧重知识面的广度。比如给你一段代码问你输出顺序给你一个CSS场景问你哪个属性可以解决给你几个HTTP头部字段问你哪个属于强缓存相关。这类题目的特点是会就是会不会就是不会蒙对的概率不高。它考察的是日常积累比如有没有认真看过《JavaScript高级程序设计》、有没有系统刷过CSS的文档。简答题侧重知识深度与表达能力。典型的有讲讲浏览器从输入URL到页面渲染的完整过程说说JSONP的原理和局限解释一下React的diff算法。这类题没有标准答案但判卷人有明确的采分点。比如URL到渲染这道题能答出DNS解析、TCP连接、HTTP请求、DOM解析、CSSOM构建、渲染树合成、布局、绘制这些关键节点的基本就能拿满分只答了发起请求然后渲染页面这种话的等于白写。手写编程题侧重代码功底与工程意识。常见的有手写防抖节流、实现一个深拷贝、手写Promise、数组去重、两数之和等。这类题目的坑在于看起来简单但边界条件极多。比如深拷贝很多人只处理了普通对象和数组没处理循环引用、Date、RegExp、Symbol属性直接挂掉。这部分对代码习惯的要求很高变量命名是否清晰、边界判断是否完整、代码是否简洁都会影响最终得分。从时间分配上看我建议选择题控制在总时长的30%以内简答题控制在35%左右剩下的35%以上留给手写编程题。很多考生挂在编程题上不是因为不会而是因为前面磨蹭太久导致后面代码题根本没时间写完或者写完了没时间检查边界条件。笔试卷考的不只是你会不会还有你在限时压力下能不能稳定输出。这个能力是需要在考前特意训练的。2. JavaScript核心考点拆解事件循环、闭包与原型链2.1 事件循环一道题就能拉开差距JavaScript的事件循环Event Loop几乎是百度这类大厂笔试卷的必考题这份第三批试卷也不例外。典型题目是这样的给一段代码包含setTimeout、Promise、async/await让你写出控制台输出顺序。console.log(script start); setTimeout(() { console.log(setTimeout); }, 0); Promise.resolve().then(() { console.log(promise1); }).then(() { console.log(promise2); }); async function foo() { console.log(async1); await bar(); console.log(async2); } async function bar() { console.log(bar); } foo(); console.log(script end);正确的输出顺序是script start → async1 → bar → script end → promise1 → promise2 → async2 → setTimeout。但实际考试中能做到完全答对的考生不超过三成。这道题的解题关键是两条规则。第一JavaScript是单线程的任务分为同步任务和异步任务同步任务先执行。第二异步任务又分为宏任务macrotask和微任务microtask微任务优先于宏任务执行而且微任务队列会在当前宏任务结束前被清空。具体到上面的代码先把所有同步代码执行完所以先是script start、async1、bar、script end。注意async函数里的await它会把后面的代码包装成微任务。然后处理微任务队列promise1、promise2、async2在这里都排到了setTimeout前面。最后才是宏任务setTimeout。注意async/await只是Promise的语法糖await后面的代码要看Promise的微任务行为。很多人把await当成同步代码来理解这是最容易踩的坑。这道题考查的核心不是你能不能背出输出结果而是你理解不理解浏览器和Node环境里事件循环的差异以及宏任务和微任务的执行优先级。备考时建议把事件循环的细节彻底搞懂不要只背题因为换个写法你就要重新推理。理解一个模型胜过硬背十道题。2.2 闭包与原型链从概念到应用场景闭包是另一道绕不开的题。笔试里常见的考法有两种第一种是概念题直接问什么是闭包有什么优缺点第二种是看代码题让你分析某个循环里用var声明的变量为什么输出不对以及怎么用闭包修复。for (var i 0; i 5; i) { setTimeout(() { console.log(i); }, 1000); } // 输出 5 5 5 5 5学过闭包的人都知道这是因为setTimeout回调函数里的i引用的是同一个变量i循环结束后i已经变成了5。解决方案有两个一是用let替代var因为let有块级作用域每次循环都会重新绑定变量二是用闭包把i保存下来for (var i 0; i 5; i) { (function (j) { setTimeout(() { console.log(j); }, 1000); })(i); }但笔试不会只考到这里。真正拉分的追问是闭包的原理是什么为什么函数能访问外部变量这就需要你理解作用域链和词法作用域。闭包的底层机制是当函数被定义时它会捕获当前词法环境形成作用域链即使外部函数执行完毕内部函数依然持有对外部作用域变量的引用导致这些变量不会被垃圾回收。闭包在工程里的典型应用有三个数据私有化用闭包实现模块化把变量藏在函数作用域内、函数柯里化、防抖节流。这三个应用一旦写出来考官就知道你不是纸上谈兵。原型链的考法和闭包类似不考定义考继承的实现和属性查找机制。典型题目实现一个寄生组合式继承或者问你new一个对象的过程中this和prototype分别发生了什么。new的底层逻辑其实就四步创建一个空对象将这个空对象的__proto__指向构造函数的prototype将构造函数的this绑定到这个空对象上并执行如果构造函数没有显式返回对象则返回这个新对象。理解了这个过程你就能解释清楚instanceof的原理也能明白为什么ES6的class本质上是语法糖。这里我建议备考时把JavaScript高程里关于面向对象那一章反复看三遍把原型链的图自己亲手画一遍比背一百道题都有用。2.3 手写Promise最经典的手写代码题手写Promise在百度笔试及面试中出现频率极高。这道题看似只考一个知识点实际上串联了状态机、回调函数、异步调度、错误处理、以及Class语法等多个知识点。一份合格的手写Promise至少要满足以下功能class MyPromise { constructor(executor) { this.state pending; this.value undefined; this.reason undefined; this.onFulfilledCallbacks []; this.onRejectedCallbacks []; const resolve (value) { if (this.state pending) { this.state fulfilled; this.value value; this.onFulfilledCallbacks.forEach(fn fn()); } }; const reject (reason) { if (this.state pending) { this.state rejected; this.reason reason; this.onRejectedCallbacks.forEach(fn fn()); } }; try { executor(resolve, reject); } catch (e) { reject(e); } } then(onFulfilled, onRejected) { onFulfilled typeof onFulfilled function ? onFulfilled : value value; onRejected typeof onRejected function ? onRejected : reason { throw reason }; const promise2 new MyPromise((resolve, reject) { if (this.state fulfilled) { setTimeout(() { try { const x onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); } if (this.state rejected) { setTimeout(() { try { const x onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); } if (this.state pending) { this.onFulfilledCallbacks.push(() { setTimeout(() { try { const x onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); }); this.onRejectedCallbacks.push(() { setTimeout(() { try { const x onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); }); } }); return promise2; } }这样写已经能覆盖大部分笔试要求。注意几个关键细节状态一旦改变就不能再变then里回调的执行需要在setTimeout中异步执行保证符合规范then必须返回一个新的Promise以支持链式调用。最后还有一个resolvePromise函数用来处理then回调返回Promise的情况这里不再展开。实测下来能把上面这些逻辑完整、正确地写出来的人很少。很多人卡在then里要处理回调返回Promise这一步因为这涉及状态传递的递归逻辑。备考的话我建议先理解Promise/A规范再自己默写两遍这份代码在笔试中一旦出现就是一道直接的筛选器。3. 浏览器工作原理与网络协议前端工程师的必修课3.1 从输入URL到页面渲染一道必考的综合性大题在地址栏输入URL并回车到页面最终显示中间发生了什么这道题在这份试卷里出现了在其他大厂试卷里也几乎是标配。作为前端工程师这道题答得好不好直接反映了你对自己日常工作的理解深度。完整的链路可以拆成九个环节URL解析、DNS查询、TCP连接建立、发送HTTP请求、服务器处理并返回响应、浏览器解析HTML构建DOM树、解析CSS构建CSSOM、DOM树和CSSOM树合成渲染树、布局与绘制。笔试作答时很多同学容易漏掉两点。第一DNS查询是有缓存层级的从浏览器缓存、操作系统缓存、路由器缓存到本地DNS服务器再到根域名服务器、顶级域名服务器、权威域名服务器是一个逐级递归查询的过程。第二TCP连接建立时有三次握手而且现在大量网站已经用了HTTPS还需要额外的TLS握手。这两个细节一写进去整道题的完整度和档次立刻不一样。关于渲染过程这里要展开强调一下。HTML解析器是从上到下逐行解析HTML的遇到CSS会请求并解析CSS遇到JavaScript脚本会暂停HTML解析先下载并执行脚本除非加了defer或async属性。这就是为什么经典的建议是CSS放头部、JavaScript放底部来优化首屏速度。解析完成后DOM树和CSSOM树会合成渲染树渲染树只包含可见节点然后经过布局确定每个节点的几何位置最后通过绘制把像素呈现到屏幕上这个过程中还涉及合成层的处理。笔试还有一个常考的追问重排reflow和重绘repaint有什么区别重排是当元素的几何属性发生变化时需要重新计算布局重绘是当元素的外观属性发生变化但几何属性不变时只需要重新绘制。重排一定导致重绘重绘不一定导致重排。优化手段就是尽量减少重排次数比如用transform替代top/left做动画用class批量修改样式避免逐条修改style属性等。这个追问如果答得好说明你是真的写过性能优化的不是背的。3.2 HTTP缓存机制强缓存与协商缓存HTTP缓存这道题在这份试卷里以给一组响应头判断缓存策略的形式出现。缓存机制是浏览器提速的核心手段之一前端工程师必须吃透。整个缓存机制可以分成两条线。第一条线是强缓存浏览器请求资源时先检查本地缓存是否命中。命中强缓存的条件是响应头里有Cache-Control或Expires并且缓存未过期。Cache-Control: max-age3600表示缓存生效3600秒这是HTTP/1.1的标准方案Expires是HTTP/1.0的方案指定一个绝对过期时间但因为依赖客户端时间容易出错现在一般以Cache-Control为准。第二条线是协商缓存当强缓存未命中时浏览器会带着上次响应中记录的标识向服务器发起请求由服务器判断资源是否发生变化。这个标识有两种ETag资源内容哈希和Last-Modified最后修改时间。服务器如果判断资源没变返回304 Not Modified浏览器继续用本地缓存如果变了返回200和新的资源内容。笔试常见的出题方式是给你一段响应头让你判断刷新页面的请求命中的是强缓存还是协商缓存为什么会出现304。还有一个高频考点是设置了Cache-Control: no-cache意味着什么注意no-cache不是不缓存而是每次使用缓存前都要向服务器验证——它强制走协商缓存。真正不缓存的是no-store。这里我给出一个建议备考时把这张缓存决策表记牢——有强缓存标识且未过期直接使用本地缓存不发请求强缓存过期带协商标识发请求服务器返回304则用旧缓存返回200则用新资源。这个决策流程在笔试中能用文字表述出来在面试中也经得起追问。3.3 跨域从原理到五种解决方案跨域问题几乎是前端笔试的常青树。这份试卷里涉及了一个场景题A站点要请求B站点接口问如何处理跨域以及为什么会有这个限制。跨域限制的根源是浏览器的同源策略。同源指的是协议、域名、端口三者都相同任何一项不同就会产生跨域。浏览器限制跨域本质上是安全措施防止恶意网站读取其他网站的数据。注意一个细节跨域限制是浏览器端的限制不是说服务端收不到请求而是浏览器拦截了响应所以CORS跨域资源共享的核心思路是让服务器告诉浏览器这个跨域请求我允许。做跨域的常见方案有五种JSONP、CORS、代理服务器、postMessage、以及不常用但偶尔会考到的document.domain降域。其中JSONP是面试的高频考点因为它的原理非常考基本功利用script标签不受同源策略限制的特性动态加载一个外部脚本服务器返回一段函数调用代码把数据作为参数传进去。function jsonp(url, callbackName, callback) { const script document.createElement(script); script.src ${url}?callback${callbackName}; window[callbackName] function (data) { callback(data); document.body.removeChild(script); }; document.body.appendChild(script); }JSONP有个明显的局限只支持GET请求没有完整的错误处理机制。所以现代开发更多用CORS。CORS的实现核心在服务端加Access-Control-Allow-Origin响应头。如果请求比较复杂比如带自定义头、用PUT方法会先触发一个OPTIONS预检请求这也是笔试里容易考的点。关于CORS只需记住一句话只要服务端配合设置响应头跨域就能放开不配合前端怎么折腾都不行。笔试里还有一道关于代理服务器的题前端开发环境的跨域代理比如webpack-dev-server的proxy原理是什么答案就是让开发服务器转发请求绕开浏览器的同源限制。这种题能答好的人说明真的在工程里处理过跨域不是只会背概念。4. CSS考点拆解盒模型、BFC与布局方案4.1 盒模型与BFC一道题考出布局功底CSS部分在这份试卷里的占比不低而最经典的题目就是盒模型和BFC。盒模型的题目通常是以下代码中一个元素的width是100pxpadding是20pxborder是5px在不设置box-sizing的情况下这个元素实际占用的宽度是多少答案是150px。因为在默认的content-box模型下width指content的宽度实际总宽度要加上padding和border。而如果设置了box-sizing: border-box那么width就包含了padding和border实际总宽度就是100px。这道题答错的人非常多因为很多人在工程里天天用border-box却不知道它到底改变了什么。BFC的题目则更偏应用。BFC全称Block Formatting Context块级格式化上下文。可以把它理解为一个独立的渲染区域这个区域里的元素布局不会影响外部元素。触发BFC的条件也很值得记根元素html、float不为none、position为absolute或fixed、display为inline-block或flex或grid或table-cell、overflow不为visible。BFC在笔试中最常考的三个场景清除浮动带来的高度塌陷、阻止垂直margin合并、阻止元素被浮动元素覆盖。比如经典的父元素高度塌陷问题子元素设置了float父元素高度变成0解决办法就是给父元素加overflow: hidden触发BFC。这个方案能讲清楚原理的候选人布局功底基本就过关了。4.2 垂直水平居中一题多解背后的思维差异垂直水平居中是一个看起来简单的题但这份试卷通过它考察了候选人掌握多少种布局方案以及是否能区分不同方案的适用场景。笔试中写出一种方案只能拿基础分写出三种以上并说明各自的优缺点才是满分的状态。我在这里把主流方案整理成一个对照表方案实现方式适用场景缺点绝对定位负margin已知元素宽高静态尺寸元素宽高变化时需要调整绝对定位transform宽高未知也可用通用transform可能影响其他动画flex布局parent设flex align/justify现代浏览器项目兼容旧浏览器麻烦grid布局parent设grid place-items简单且现代兼容性要求高表格单元格display: table-cell兼容IE老版本多了一层包裹结构答题时的加分技巧是指出flex布局一行代码解决的是子元素的居中grid的place-items: center更是三行变一行同时说明在必须兼容老IE的项目里为什么仍然要心平气和地使用绝对定位或table-cell方案。这种能根据场景选方案的意识正是大厂想要的东西。4.3 Flex布局与响应式新题型的重灾区2019年的这份试卷Flex布局已经占了不少比重。典型的题目是给定一个Flex容器里面有若干子元素问你flex: 1表示什么flex-grow、flex-shrink、flex-basis三者分别控制什么flex: 1是flex-grow: 1、flex-shrink: 1、flex-basis: 0%的缩写。flex-grow控制空间有剩余时如何放大flex-shrink控制空间不足时如何缩小flex-basis决定项目在主轴上的初始大小。很多考生答得出flex-grow的放大效果但一问flex-basis和width谁优先级更高就懵了。实际上flex-basis优先级高于width如果flex-basis设置了具体值width会被忽略。试卷里还有一道关于响应式的题目怎么样实现一个移动端优先的页面常见答案有三个层次用媒体查询在不同断点下调整布局、用rem或vw/vh做相对单位的适配、用flex或grid实现弹性伸缩布局。答这三个层面的逻辑顺序也有讲究通常先说flex弹性布局是自然响应的基底再谈媒体查询处理特殊断点最后用相对单位解决字体和间距适配。这个顺序本身就是思维清晰的体现。另外可以补充一个工程经验移动端适配可以通过设置viewport和基于设计稿宽度换算rem基准值比如以375px为基准1rem等于100px这样开发时直接用设计稿数值除以100即可实现成本很低。5. 算法与手写编程题笔试的决胜区5.1 高频算法题型的出题规律大厂笔试的算法题通常不会出纯LeetCode的Hard题而是偏好业务场景包装过的基础算法题。百度这份试卷同样如此常见的有数组去重、字符串反转、两数之和、防抖节流、深拷贝、实现Array的原生方法等。数组去重这道题考察的是对数组API的熟悉程度和对时间复杂度的理解。最简单的写法是Setconst arr [1, 2, 2, 3, 4, 4, 5]; const unique [...new Set(arr)];但如果题目要求不能使用Set或者要求考虑大数组的性能就需要写出双循环去重或使用对象键值对去重。笔试中能写出时间复杂度和空间复杂度分析的属于加分项。比如用对象键值对去重的时间复杂度是O(n)但要注意区分字符串和数字时对象键的隐式转换问题用Map可以避免这个问题。防抖和节流是工程中最高频的手写题也是这份试卷的大概率考点。这里的核心不是把代码背下来而是理解两者的差异防抖是停止触发后延迟执行适合搜索框输入的场景节流是固定时间间隔内最多执行一次适合滚动监听和窗口resize。function debounce(fn, delay 300) { let timer null; return function (...args) { if (timer) clearTimeout(timer); timer setTimeout(() { fn.apply(this, args); }, delay); }; } function throttle(fn, interval 300) { let last 0; return function (...args) { const now Date.now(); if (now - last interval) { last now; fn.apply(this, args); } }; }注意代码里的this处理使用普通函数而不是箭头函数确保调用时this正确传递。如果你用箭头函数写this会绑定到定义时的上下文在事件监听场景里就会出错。这个细节很多人写的时候意识不到但笔试会有眼尖的面试官看到。5.2 手写代码题的边界条件与代码规范手写编程题的评分维度除了正确性还有边界条件的完整性和代码可读性。我给你一个自查清单数组为空时能不能跑输入的是字符串怎么办参数没传怎么办会不会出现死循环函数命名是否表明了用途以深拷贝为例最高频的写法是递归拷贝但很多人的第一版就会踩循环引用的坑——对象里包含对自身的引用时递归会无限循环导致栈溢出。解决思路是用WeakMap记录已拷贝的对象遇到重复引用直接返回之前拷贝的结果。还能处理Date、RegExp、Map、Set这些特殊对象类型的话这道题就是满分水准。function deepClone(target, map new WeakMap()) { if (typeof target ! object || target null) { return target; } if (map.has(target)) return map.get(target); const result Array.isArray(target) ? [] : {}; map.set(target, result); if (Object.prototype.toString.call(target) [object Date]) { return new Date(target.getTime()); } if (Object.prototype.toString.call(target) [object RegExp]) { return new RegExp(target.source, target.flags); } if (target instanceof Map) { target.forEach((value, key) result.set(key, deepClone(value, map))); return result; } if (target instanceof Set) { target.forEach(value result.add(deepClone(value, map))); return result; } const keys [...Object.getOwnPropertyNames(target), ...Object.getOwnPropertySymbols(target)]; keys.forEach(key { result[key] deepClone(target[key], map); }); return result; }代码规范上有三个小细节特别加分。第一变量名有意义不要用a、b、tmp这种第二每个函数控制在20行以内过长说明逻辑可以拆解第三关键步骤加一行注释帮助阅卷人快速理解你的思路。在笔试场景里阅卷人一天看几百份卷子一份逻辑清晰、命名规范、注释到位的代码一定会比一份虽然正确但乱糟糟的代码获得更好的评价。6. 实战经验笔试中的时间管理、失分点与备考路径6.1 时间分配与做题顺序的实战策略根据我帮人复盘这套试卷的经验掌握合理的做题顺序能直接提升5到10分。我的建议是先花两分钟通读全卷标记出所有手写编程题然后按照先编程题、再简答题、最后选择题的顺序作答。为什么这样安排因为手写编程题的思考量和书写量最大在考试最后阶段大脑疲劳的时候写代码出错率会明显上升。而选择题即使时间紧张也有一定的蒙答可能。很多人习惯从头做到尾结果到最后十分钟才看到最后的编程题匆匆写了两行就交了这是最可惜的情况。每一道编程题建议的做法是先在草稿纸上把思路和数据结构画清楚再动手写。不少考生看到题目就开始敲代码写到一半发现逻辑方向错了删掉重来白白浪费十五分钟。先在草稿纸上列清楚输入输出、边界条件、算法步骤五分钟后开始写整个过程的效率反而更高。这是我在实际开发中也坚持的习惯先设计再编码笔试场景同样适用。6.2 从高频失分点反推复习方向复盘这份试卷考生失分最严重的点通常集中在下面几个地方。第一对Flex布局的理解停留在会用的层面答不出flex-basis和width的优先级关系、答不出flex-shrink的收缩规则。第二对HTTP缓存中no-cache与no-store的区别模糊被问到就直接丢分。第三手写Promise时处理不了then回调返回Promise的情形链式调用直接断掉。第四深拷贝不处理循环引用代码在特殊输入下崩溃。这些失分点反馈出一个共性问题很多人的前端基础是工程经验导向的常用功能会写底层原理讲不透。但大厂笔试考的就是原理。我的建议是花两周时间把以下三块内容系统过一遍其一JavaScript核心机制包括执行上下文、作用域、闭包、事件循环、面向对象与原型链其二浏览器工作原理包括渲染流程、缓存机制、存储方案其三CSS布局规范包括盒模型、BFC、Flex、Grid。这三块覆盖了大厂笔试试卷的八成考点。6.3 备考资料与刷题路线的个人建议关于备考资料我不推荐贪多。吃透两本经典书比泛读十本书有效得多一本是《JavaScript高级程序设计第4版》别把它当字典查按章节顺序过一遍重点看执行上下文、原型链、Promise、事件循环这几章每章看完自己写段总结代码另一本是《CSS权威指南》主要看盒模型、格式化上下文、定位和弹性布局部分。算法部分不需要把LeetCode全部刷完把数组、字符串、链表、二叉树四类题各刷三十道重点掌握双指针、哈希表、递归这些高频思路就行。刷题的过程有个小技巧不要边看答案边写。把题目做不出来时的卡壳点记录下来对照题解后重新默写一遍。下次再遇到同类题能在不看答案的情况下完整写出来才算真正会了。面试和笔试的差距就在于背答案的人会在稍微变形的题目前露出马脚而真正理解原理的人能从容应对。最后再分享一个我个人的体会笔试只是敲门砖它考的是基础而基础是前端工程师唯一的护城河。框架每年都在更迭工具链换了又换但事件循环没有变、原型链没有变、HTTP协议没有变、布局原理没有变。把这份试卷当成一次体检每一道错题都对应一个知识盲区把这些盲区一个个补上你收获的不仅仅是过笔试的能力更是长期从事Web前端开发的核心竞争力。多花点时间把底层原理啃下来是这笔投资永远不会亏的交易。
返回列表