ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

小米2020前端笔试题解析:从JS基础到浏览器原理的考点全拆解

小米2020前端笔试题解析:从JS基础到浏览器原理的考点全拆解 一份工作摆了四年回头再看小米2020校招前端工程师笔试题二依然觉得它把“基本功检测”这件事做得相当到位。很多同学在校招季疯狂刷LeetCode却在这套题的选择题和简答题上翻了车原因不在于难度而在于考察的东西太基础基础到很多人平时根本没当回事。今天不聊“小米有多香”单纯从这套笔试题出发拆一下它到底在考什么、每类题背后的考察意图是什么、以及准备这类笔试的正确姿势是什么。先泼一盆冷水这套题和“刷题型”的笔试不一样它没有任何偏题怪题几乎每一道都能在前端基础知识和《JavaScript高级程序设计》里找到出处。但正因为如此它对“是否真的理解前端”的区分度极高。能把这套题答好的人不是背题背出来的而是平时写代码时就会主动追问“为什么”的人。1. 这套笔试题到底在筛什么从题型分布看小米的用人标准先说结论小米2020校招前端笔试题二整卷看下来考察重心非常清晰按分值占比排序依次是JavaScript语言基础、浏览器与网络原理、CSS布局与样式细节、前端工程化常识最后才是两道算法题。这个分布和很多互联网大厂的笔试有明显区别后者动辄三四道hard级算法题而小米更在意候选人的前端专业底色。我后来复盘当时做题的感受这套题大概由四部分组成单选题、多选题、简答题和编程题。单选题主要集中在语言细节比如typeof null的结果、和的区别、数组方法的返回值、this指向这类问题多选题则会埋一些“看起来对但其实有一个选项错”的陷阱考察对知识边界的掌握是否精准简答题几乎都围绕事件循环、闭包、原型链、浏览器缓存这类高频主题展开需要你用书面语言把原理讲清楚编程题则是常规的数组去重、深拷贝、手写某个API或者简单的数据处理逻辑。这个结构透露出几个信号。第一小米校招并不指望应届生有丰富项目经验但默认你应该把大学期间自学的或者科班教的基础知识吃透。第二选择题和简答题的结合说明他们既关注你对结论的记忆也关注你对原理的表达。第三算法题占比不高、难度适中说明他们更看重前端领域内的思维方式而不是把前端岗当成通用软件工程师来招。从这个角度回看我给准备前端校招的同学一个建议不要盲目跟风刷算法题先把JavaScript、CSS、HTTP这些地基打牢。小米这套题如果能在45分钟内做到选择题全对、简答题逻辑清晰、编程题跑通哪怕没有亮眼项目进面试的概率也非常大。因为笔试筛掉的正是那些浮于表面、“会用框架但不懂语言”的人。2. JavaScript核心考点精讲从变量提升到事件循环JavaScript部分在这套题里占比最大考点也最典型。我挑几个高频题目类型把背后的原理和答题思路展开说说这些在考场上只要你理解了根本不需要背。2.1 变量提升与暂时性死区有一道选择题大概是这样的以下代码输出什么console.log(a); var a 1; console.log(b); let b 2;答案是先输出undefined然后报错ReferenceError。这道题本身不难但它同时考察了var的变量提升和let的暂时性死区。var声明的变量在编译阶段会被提升到作用域顶部赋值留在原地所以console.log(a)能访问到a只是值是undefined。而let虽然也会被提升但在初始化之前访问它会进入暂时性死区TDZ直接抛错。这类题的答题要点是把“提升”和“初始化”分开说。很多同学只知道“var会提升let不会”这个理解其实不准确let也提升只是不允许在初始化前访问。把这个区分讲清楚阅卷人一眼就知道你是真懂还是背过概念。2.2 this指向的四种绑定规则this指向问题几乎是大厂前端笔试的必考题小米这套也不例外。考题常见形式是给出一个对象方法、一个普通函数、一个箭头函数问调用后的输出。常规考的规则就四条默认绑定、隐式绑定、显式绑定、new绑定。优先级从低到高是默认绑定小于隐式绑定小于显式绑定call/apply/bind小于new绑定箭头函数则不适用以上任何规则它继承外层作用域的this。我在做题时发现一个容易丢分的地方严格模式下的默认绑定。如果函数体内是use strict独立调用的函数内部this是undefined而不是window。有些选择题故意不写严格模式有些写你得看清题目条件再下笔。2.3 事件循环与宏任务微任务这是简答题的热门选手几乎每一届校招都考。小米2020的题目大概是写出下面代码的输出顺序。console.log(1); setTimeout(() console.log(2), 0); Promise.resolve().then(() console.log(3)); console.log(4);正确答案是1, 4, 3, 2。背后的逻辑是同步代码先执行微任务队列在同步代码结束后、宏任务之前清空。Promise.then注册的是微任务setTimeout注册的是宏任务。但要拿高分不能只写到这一层。我当时在简答题里把完整的事件循环机制写了出来调用栈执行同步代码遇到异步API交给Web APIs处理回调按类型进入宏任务队列或微任务队列当前宏任务执行完后清空微任务队列再取出下一个宏任务执行如此反复。具体到浏览器环境还要提一下requestAnimationFrame的执行时机在微任务之后、渲染之前。这样答出来深度一下子就上去了。2.4 闭包与内存释放闭包概念题考的形式很多可能是让写一个防抖节流函数可能是问某段代码为什么能访问外部变量也可能是问问闭包带来的内存问题。核心要把三句话说明白闭包就是函数能够记住并访问所在词法作用域即使外层函数执行完毕内部函数依然持有对外层变量的引用闭包会导致这些变量不被垃圾回收如果滥用可能造成内存泄漏。但这里有个易错点不能说“闭包一定会导致内存泄漏”。内存泄漏的根因是意外保留而不是闭包本身。只要闭包的生命周期合理它就不会泄漏。答题时可以举一个实际的例子比如节流函数里用闭包保存上一次执行的时间戳这个变量需要在多次调用之间存活那么闭包就是最自然的选择。这样答既讲原理又讲应用比干巴巴念定义强太多。3. CSS与布局计算考点简单但细节拉满CSS部分在很多人眼里是“背属性”的送分题但小米这套题恰恰在CSS上埋了不少“看着会、做着错”的细节。它不考刁钻的动画曲线也不考冷门属性而是把最常见的知识点往深了挖。3.1 盒模型一道计算题引发的血案有一道经典题一个div宽度设了200pxpadding是20pxborder是5px在content-box和border-box两种模型下占用的总宽度分别是多少content-box默认下总宽度是200 20*2 5*2 250pxborder-box下总宽度就是设置的200px内容宽度会被压缩成200 - 40 - 10 150px。这道题的坑有两个一是很多同学忘记上下左右都要算双份二是没有理解box-sizing改变的是width属性的作用对象。实际上box-sizing: border-box解决的是“百分比高度、百分比宽度在设置padding后破版”的问题这是移动端布局时几乎必写的属性。答题时顺手补充这个工程背景能体现你不是死记硬背。3.2 垂直水平居中全家桶小米这套题的简答题或者多选题里一定会有“如何实现一个元素在父容器内水平垂直居中”的题。关键是你得在一道题里写出尽可能多的方案并说清各自的适用场景。我通常给出的方案如下方案核心代码适用场景flex父容器display:flex; align-items:center; justify-content:center;通用日常首选grid父容器display:grid; place-items:center;现代浏览器绝对定位负margin子元素position:absolute; top:50%; left:50%; margin-left:-width/2; margin-top:-height/2;需要兼容老浏览器且宽高已知绝对定位transform子元素position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);宽高未知时使用table-cell父容器display:table-cell; text-align:center; vertical-align:middle;兼容老旧场景margin:auto绝对定位子元素inset:0; margin:auto;有宽高时答题时最后一定要补一句flex和grid是现代布局的主流方案但在某些必须兼容IE的场景下还是要用绝对定位或table-cell兜底。这句话说明你是有工程经验的不是只会写“标准答案”的应届生。3.3 BFC与边距重叠BFC块级格式化上下文是CSS笔试里的老面孔小米也爱考。常见考法有两种问“如何触发BFC”或者问“两个相邻div的margin怎么算”。触发BFC的条件有float不为none、position为absolute或fixed、display为inline-block、flex/grid等、overflow不为visible、contain为layout等。相邻兄弟元素的上下margin会取较大值而不是相加父子元素的margin如果紧挨着也会重叠解决办法是给父元素创建BFC或者加一层padding/border隔开。这类题的答题策略是“条件加例子”不要只罗列条件。比如可以写“父元素和第一个子元素都设置了margin-top结果父元素被顶下去了怎么解决”先描述现象再给出方案最后解释原理。这种答法在笔试阅卷时很容易拿高分因为展示了排查问题的完整链路。4. 浏览器与HTTP原理网络层考点背后的工程价值前端笔试考浏览器原理和HTTP不是考网络工程师的八股而是考察你在真实开发中能否定位性能问题、能否理解页面加载的每一个环节。小米这套题在这一块的选择题和简答题出得很务实。4.1 从输入URL到页面展示的完整过程这道题几乎每个大厂笔试都会出现小米2020也问了而且明确要求按顺序写出关键步骤。标准答案大概是DNS解析、建立TCP连接、发送HTTP请求、服务器处理并返回响应、浏览器解析HTML、构建DOM树、构建CSSOM树、合并成渲染树、布局、绘制、合成显示。只写这些还是基础。想拿高分需要补充几个容易被忽略的点DNS缓存查询顺序浏览器缓存、系统缓存、路由器缓存、根DNS服务器HTTPS建连时的TLS握手HTML解析过程中遇到script标签会阻塞DOM解析遇到带async或defer的脚本行为不同CSS的加载会阻塞渲染但不会阻塞DOM解析图片的加载是异步的不阻塞DOM解析。这些细节在选择题部分很可能就会换成另一种形式出现比如“在HTML解析过程中遇到script标签以下哪种说法正确”。你如果只背过“JS会阻塞解析”这句口诀而不知道defer和async的区别这题就必错。4.2 浏览器缓存强缓存与协商缓存关于缓存几乎每届校招都有一道题而且它不只是在笔试里考面试也必问。答题时要分清楚两个维度一是强制缓存和协商缓存二是分别用了什么字段。强制缓存返回200 from cache服务端通过Cache-Control: max-ageseconds和Expires控制。Cache-Control优先级高于Expires且Expires受本地时间影响不稳定。协商缓存是指浏览器携带If-Modified-Since/If-None-Match发送请求服务器返回304 Not Modified则使用本地缓存对应响应头是Last-Modified和ETag。优先级上ETag高于Last-Modified因为Last-Modified粒度到秒对同一秒内多次修改的文件无能为力。这类题的加分项通常是这样一句“在实际项目中对于带hash的静态资源可以设置长期强缓存对于入口HTML文件使用no-cache走协商缓存。”这句话展示了你在真实工程里处理过缓存策略阅卷人看到这句对你的印象会完全不同。4.3 跨域问题跨域是笔试选择题的常驻嘉宾。考题喜欢给出几个请求问你哪个能成功、哪个会被浏览器拦截。核心结论就几点XMLHttpRequest和fetch受同源策略限制script、img、link标签的请求不受同源限制所以JSONP能用CORS通过服务器加Access-Control-Allow-Origin响应头解决简单请求和非简单请求的区别在于是否会触发预检OPTIONS请求携带cookie时需要设置withCredentials。答题的坑通常出现在“PostMessage、WebSocket、跨窗口通信”这些不受同源策略限制的场景。有同学一看到跨域就只写CORS和JSONP忽略了postMessage、document.domain、window.name这些方案。建议把每种方案的核心代码或者关键配置点列一下保证选择题不管怎么换都能选对。5. 算法与数据结构题前端笔试绕不开的那道送命题前面说了小米算法题占比不高但不代表没有。2020这套题里的编程题部分是两道手写题一道偏数据处理一道偏经典算法模板。我按当时考生的普遍反馈给大家梳理一下常见考法和准备思路。5.1 高频手写题数组去重、扁平化、深拷贝这三道几乎就是前端笔试的“亲儿子”。小米2020的编程题里也出现了类似场景核心是看你能不能在不借助外部库的情况下用原生JavaScript完成常见的数据处理。数组去重的标准进阶思路是// 最简单利用Set [...new Set([1, 2, 2, 3])]; // 如果要考虑对象去重需要递归判断 // 如果要保持类型区分不能用宽松相等数组扁平化的考点在于是否掌握递归和reduce的接法const flatten (arr) arr.reduce((acc, cur) Array.isArray(cur) ? acc.concat(flatten(cur)) : acc.concat(cur), []);深拷贝是重头戏。如果只写JSON.parse(JSON.stringify(obj))阅卷人会认为你只能应付面试背诵但在笔试中会扣分。因为丢掉了undefined、函数、Symbol、循环引用、Date、RegExp等特殊值。我当时给出的深拷贝核心逻辑分四步判断基础类型、处理特殊对象、递归拷贝普通对象和数组、用WeakMap解决循环引用。建议在笔试中至少写出下面这段的简化版function deepClone(target, map new WeakMap()) { if (typeof target ! object || target null) return target; if (target instanceof Date) return new Date(target); if (target instanceof RegExp) return new RegExp(target); if (map.has(target)) return map.get(target); const clone Array.isArray(target) ? [] : {}; map.set(target, clone); Object.keys(target).forEach(key { clone[key] deepClone(target[key], map); }); return clone; }这一段代码在笔试里写出来基本就能证明你理解递归、引用类型、循环引用和ES6新特性比背十道LeetCode都管用。5.2 常见算法模板排序与查找的边界条件如果编程题出到排序最稳妥的是手写快速排序或者归并排序但要写出绝对正确的版本边界条件就是分水岭。很多同学在快排的partition过程里把指针移动顺序写反导致死循环或者越界。快速排序的思路是选一个基准值把小于等于基准的放左边大于基准的放右边然后递归。这里的易错点是如果选择了最右边的元素作为基准那么从左边开始找大于基准的元素、从右边开始找小于基准的元素时必须注意先移动哪个指针。标准写法要保证最后基准位置正确交换否则结果就是错的。查找题只要不涉及复杂数据结构基本都是二分查找变种。核心边界是left right还是left right以及mid的更新是mid 1还是mid。我的经验是笔试时先把最简单、最不容易写错的写法写出来保证正确性再考虑优化。不要在考场上炫技写什么双指针加位运算出来了bug就彻底完了。5.3 笔试编程题的时间分配策略做题时最容易崩的就是时间分配。我见过不少人前面选择题花了半小时后面编程题只剩下十几分钟手忙脚乱写了个半成品。我的建议是拿到卷子先花一分钟扫一遍全卷估算每部分的耗时。如果编程题只有两道且都属于“手写API”类那前面选择题和简答题应该控制在总时间的一半左右。遇到卡壳的选择题先标记最后再回看不要在单题上耗太久。编程题的作答顺序优先级先做有把握、代码量短的题再做需要设计数据结构的题。先求正确、再求简洁、最后才考虑性能优化。笔试阅卷不会因为你用了O(n^2)的算法就全盘否定但如果连基本功能都没跑通那就是零分。6. 对照这套题反推前端校招备考的正确打开方式这套题对我的帮助不只是当年拿到面试机会更在于它让我重新梳理了前端知识体系。现在回头看至少有四个备考方向是明确的。6.1 建立以语言为核心的知识树而不是以框架为核心很多同学准备校招是从React或者Vue开始的组件生命周期、Hooks、路由鉴权背得滚瓜烂熟但一问你let和const的区别、事件循环的执行顺序就支支吾吾。小米2020这套题几乎没怎么考框架但JavaScript基础部分占了大头。这透露了一个信号校招笔试阶段默认你不会框架但要求你语言功底扎实。框架可以入职后学语言和浏览器原理才是衡量你能否胜任前端工程师的基础指标。备考时应该先把JavaScript、CSS、HTTP、浏览器原理这四块吃透再叠加框架知识。6.2 用“讲给别人听”的方式检验理解简答题能不能拿高分取决于你的表达是否清晰。我复习时有个习惯看完一个知识点关上文档用手机录音给自己讲一遍看能不能在五分钟内把原理、应用场景和易错点说完。如果说不清楚说明理解还不够。以“闭包”为例如果你能连续讲出“闭包是函数与其词法环境的组合、外层函数调用结束后内部函数仍能访问外层变量、常见的防抖节流和模块化都是它的应用、过度使用可能造成内存占用偏高”这四句话你就掌握得差不多了。这种输出式学习比看十篇博客都管用。6.3 刷题要有取舍前端岗位的算法重心和通用岗不同前端笔试的算法题大多数不会考图论、动态规划偏难题更多是围绕数组、字符串、链表、树的基础操作。重点练习这几个方向数组去重与扁平化、排序与查找、字符串处理反转、回文、大数相加、深拷贝、手写Promise、手写防抖节流、手写数组方法。当然如果你目标是大厂核心部门算法还是不能完全放至少LeetCode上的hot 100要刷完。但要在前端知识点和算法之间保持一个合理的时间分配不要本末倒置。6.4 笔试题背后的工程素养能不能落地才是分水岭有些选择题看起来是理论题但实际对应着工程里的真实场景。比如CSS盒模型那道题本质是“为什么移动端要统一设置box-sizing: border-box”事件循环那道题本质是“为什么把大规模计算拆成微任务可以避免页面卡顿”跨域那道题本质是“为什么前后端分离后要配CORS”。做题的时候如果能多问一句“这题在项目中对应哪个场景”你的答案自然就会更有层次。阅卷人看多了背诵答案忽然碰到一个能写出工程语境的考生想不给高分都难。最后的实战小技巧笔试前的三天应该干什么如果你正在准备小米或者类似大厂的前端校招笔试最后三天的复习节奏我建议这样安排第一天集中过一遍JavaScript基础题的高频考点重点是作用域、闭包、this指向、原型链、事件循环、Promise。每类考点找出对应的经典题做一遍不用多每类两三道就可以但必须做到三分钟内能完整写出核心逻辑。第二天主攻CSS和浏览器原理。把垂直居中几种方案、盒模型计算、BFC、缓存字段、跨域方案各写一遍顺便整理自己在之前笔试中经常出错的点。这部分内容少而杂最容易白捡分。第三天只做完整的一套模拟卷限时一小时模拟真实考试节奏。做完之后不要只对答案要把每道错题的知识点重新过一遍写进错题本。编程题务必在编辑器里跑一遍不要只在脑子里过。我当年就是用这套方法备考虽然没能进小米但后来在其他大厂的笔试和面试中都受益不少。回头看这套题真正考验的不是你会多少花活而是你有没有把一个前端工程师最该掌握的地基打扎实。如果你能把上面这些考点都吃透我相信不管碰到哪家的前端校招笔试题你都能稳定发挥。
返回列表