2017挖财前端笔试题复盘:闭包、事件循环与底层原理全解析

2017挖财前端笔试题复盘:闭包、事件循环与底层原理全解析 这份试卷出现在朋友圈里的那天下午我正在改一个常年没人维护的jQuery项目。微博上一堆人说挖财前端笔试不难但我点开细看之后反而觉得这份卷子比很多号称高级的面试题都值得琢磨。表面考的是JS基础、CSS布局、网络协议这些老生常谈的东西但题目设得很聪明——没有直接问概念定义而是把陷阱埋在了代码和场景里逼你把原理彻底讲清楚。2017年这个时间点很特殊Vue 2.0刚发布一年React 16刚出微信小程序年初上线前端圈正处于框架百花齐放、工程化全面铺开的躁动期。在这种环境下一份校招笔试卷没有追热点反而死磕基础说明出题人很清楚自己要什么样的人——不是背了几个框架API就来的而是底子扎实、能自己往下钻的。这份试卷我反复看了很多遍结合当时贴出来的考试内容和我自己在面试中反复问过的问题整理了一套完整的复盘。它对准备2026年校招的同学依然有参考价值因为校招笔试考的从来就不是你最近用过什么新框架而是你有没有构建自己知识体系的能力。下面我按模块拆开讲。1. 考题全景拆解这份卷子到底在筛什么人先把整份卷子的模块和权重拉出来看你会发现它跟很多人想象的前端笔试题背八股文完全不同。考察模块大致占比核心考点HTML与CSS20%盒模型、布局方案、定位机制、移动端适配JavaScript基础35%数据类型、闭包、作用域、this指向、原型链函数与异步20%防抖节流、事件循环、Promise浏览器与网络15%渲染机制、HTTP缓存、同源策略、安全框架与综合10%组件化思想、工程化意识、代码组织能力这组数据透露出一个信息JavaScript占比超过了一半。2017年前端岗位最稀缺的不是会用某个框架的人而是能把JS写明白的人。框架可以入职后学但语言本身的功底很难靠短期培训补上来。校招同学没有太多项目经验所以笔试成了观察候选人思维深度的窗口。这份卷子的题型也很有代表性选择题、简答题、手写代码题混着来。选择题考的是知识面的广度和准确度简答题考的是表达能力和概念理解深度手写代码题考的是动手能力。三块各有侧重构成一个立体的筛选漏斗。具体到每个模块的出题思路我当时跟几个参与过校招的前端朋友聊了一圈基本可以还原出出题人的想法——他大概率不是从题库里随便抽题而是按基础能力、进阶能力、潜力判断三层逻辑来设计。第一层是基础能力HTML语义化、CSS选择器优先级、盒模型。这些题保证你筛掉那些连网页基本工作原理都不清楚的候选人。第二层是进阶能力闭包、this、事件循环、原型链。这是区分会写页面和懂JS的分水岭。第三层是潜力判断手写防抖节流、手写一个简单的MVVM或事件发布订阅用来观察候选人面对没做过但可以学的问题时思路是否清晰。我当时印象最深的一道题是手写防抖函数的场景题要求在一个搜索输入框场景下实现输入停顿300毫秒后才发起请求并且要处理连续输入、快速删除等边界情况。这道题现在看依然是经典因为它同时考察了三件事对闭包的理解、对this和arguments的处理、对实际业务场景中竞态问题的思考。这种题型设计思路在2026年依然是校招笔试的主流方向。所以别再问2017年的题还有没有用这种问题了知识的表现形式在变但核心能力模型没有变。2. HTML与CSS模块菜市场大妈都能聊两句的领域反而最见功夫2.1 盒模型和定位你以为你懂了但手一写就错这份卷子里盒模型相关的题并没有直接问标准盒模型和怪异盒模型的区别而是给了一段CSS问你某元素的最终宽度是多少。这种考法比背定义高级得多因为它要求你在脑子里跑一遍浏览器渲染流程。我当时带过好几个实习生发现一个共性问题大家知道box-sizing: border-box可以把padding和border包含在宽度内但一旦遇到多个元素嵌套、父子元素都有padding和margin、还混着百分比宽度的情况计算就乱了。所以如果你在准备面试我建议你找些复杂的布局计算题来练而不是只背结论。盒模型题后面通常还跟着定位题。relative、absolute、fixed、static各自的定位参照物是谁这个很多人讲不清楚。absolute的包含块不是父元素而是最近的position不是static的祖先元素——这个考点几乎年年出现。还有margin塌陷问题。父元素没有padding或border的时候子元素的margin-top会穿透到父元素外面。解决的方案有overflow: hidden、加border、加padding、设成flex容器、或者用::before伪元素隔断。这些知识点零散但高频是校验候选人实战踩坑量的好题目。2.2 布局题圣杯和双飞翼的前世今生2017年的笔试非常喜欢考圣杯布局和双飞翼布局因为这两种布局方案代表了一个核心能力在不确定中间内容宽度的前提下用纯CSS实现左右固定、中间自适应的三栏布局。现在Flexbox和Grid大行其道很多同学觉得这类题没必要刷但我不这么看。圣杯布局的核心技巧是负margin左右两栏各宽200px中间栏宽度100%把三栏丢进同一个容器里然后通过margin-left: -100%把左栏拉回最左边margin-right: -200px把右栏拉回最右边再给容器左右各留出200px的padding最后用position: relative配合left和right把左右栏固定到正确位置。双飞翼布局思路不同中间栏内部再包一层div左右两栏依然用负margin拉回但中间那层通过margin把左右空间让出来不需要额外定位。这两种方案在2026年的实际项目中已经很少直接手写了Flex一行justify-content: space-between就能搞定大半场景。但笔试考它的逻辑在于负margin和浮动机制是理解CSS布局原理的重要节点能把这两种布局吃透的人说明对文档流、浮动、定位这些底层概念是有感觉的。我建议你把它们当作原理练习题来对待不要当作工作技能来死记。2.3 移动端适配rem、1px和视口的故事2017年是移动端适配题最热的一年。flexible.js方案当时很流行核心思路是把设备宽度分成10份1rem等于根元素字体大小通过动态修改html的font-size来实现等比缩放。笔试里经常给一个设计稿宽度比如750px问你在屏宽375px的设备上某个元素应该写多少rem。这道题其实考的是对rem本质的理解。设计稿750px说明1rem对应的设计稿像素是75px。真实设备屏宽375px根元素字体设为37.5px那么设计稿里的100px就写成100/751.3333rem。你能算出这个数说明理解了计算公式你还能说出为什么不用em——因为em参照的是父元素字体大小嵌套层级一多就乱套了。还有经典的1px问题在dpr2的Retina屏上CSS的1px实际占2个物理像素看起来太粗。解决方案有transform: scale(0.5)、用box-shadow模拟、用border-image各有优劣。这些题放到今天依然是移动端的高频题因为真机上遇到的问题没有消失只是换了问法。3. JavaScript模块笔试的主战场成败全在这里3.1 数据类型和判断从typeof到Object.prototype.toString这份卷子关于数据类型的题基本把typeof的坑都踩了一遍typeof null输出objecttypeof function(){}输出functiontypeof []输出object。如果只考这些题目不难但2017年的笔试题很喜欢加一个变体——如何准确判断一个值的类型。准确判断需要用到Object.prototype.toString.call(value)。这个方法返回[object Array]、[object String]、[object Null]这种格式比instanceof可靠得多因为instanceof在多窗口场景下会失效——不同iframe里Array的构造器不是一个。我当时给团队招人的时候最怕遇到只会背答案但解释不了原理的候选人。所以如果你现在准备笔试别停留在记住typeof null是object的层面你要问自己为什么null会被typeof识别为object这其实是JS第一版设计时留下的历史包袱二进制前三位是0的都会被当成object类型null的全零二进制正好命中。这种知其所以然的深度是面试官最想看到的。3.2 闭包、作用域和this一道题能问出半小时闭包在2017年的废卷率里贡献了最大份额。常见的考法是给出一个for循环循环里用var声明变量然后往数组里push一个打印该变量的函数最后循环外执行问打印结果。答案是全打同一个值而非0到4。原因在于var没有块级作用域循环变量被提升到了函数作用域所有函数共享同一个变量。解决方式有两个用let声明让每次循环生成独立的块级作用域或者用立即执行函数IIFE把每次的i作为参数传入形成闭包保存。这个考点后面一定跟着this指向题。我见过一道很典型的题对象里有个方法方法内部有个普通函数普通函数内部用this.xxx取值问输出什么。很多人会脱口而出取到对象上的属性实际上普通函数的this指向调用者此处直接调用非严格模式下指向window严格模式下是undefined。接下来还会跟一道call、apply、bind的题问你区别和手写实现。call和apply都是立即执行区别是传参方式bind返回新函数且新函数的this永久绑定。手写bind的时候要注意两点第一新函数被new调用时绑定失效this指向新实例第二需要考虑参数拼接。这两点当年就有人踩坑现在依然是高频考点。3.3 事件循环宏任务和微任务的顺序题事件循环是2017年笔试里我最喜欢给候选人讲的一道题因为它的区分度极高。不了解事件循环的人遇到输出顺序题会靠猜理解的人能在几秒内推出来。典型题console.log(1)、setTimeout(() console.log(2), 0)、Promise.resolve().then(() console.log(3))、console.log(4)问输出顺序。正确答案是1、4、3、2。解释起来也不复杂先执行完整个同步代码然后处理微任务队列Promise的then回调最后才轮到宏任务setTimeout。这个过程是整体循环每一轮宏任务结束后清空微任务队列而不是微任务永远排在宏任务前面这么简单。如果微任务里又注册了微任务会再本轮清空一直执行到微任务队列为空。setTimeout的第二个参数是0也不是说立刻执行而是最少延迟0毫秒实际还得等前面排队。这类题在2026年依然是前端面试的绝对主力因为异步编程能力直接决定了你能否写好业务代码。Node.js那边的setImmediate、process.nextTick还会再复杂一层但最开始入门先把手动推演浏览器端的输出顺序练熟就够了。3.4 原型链和继承最考验理解深度的知识块原型链相关的题目是2017年这份笔试里区分度最大的一块。选择题让你判断一段代码输出是什么简答题让你画一个原型链关系图手写题让你实现一个继承。原型链的本质是对象与对象之间通过__proto__串联起来的委托关系。访问对象属性时先在自身找找不到就往__proto__指向的构造函数的prototype上找再找不到就继续往上直到Object.prototype再往上就是null。这种设计让实例方法和静态方法有了完全不同的存储位置也让hasOwnProperty和in操作符有了语义差异。继承的实现方案在2017年经常考三种原型链继承、构造函数继承、组合式继承。组合式继承用SuperClass.call(this)来继承实例属性用Child.prototype new SuperClass()来继承方法能满足大多数场景。但这种方式会调用两次父构造函数后来有了寄生组合继承通过Object.create(SuperClass.prototype)来避免多余的调用。ES6的class和extends只是语法糖底层还是这套机制。所以就算你用class写代码也建议把原型链讲清楚。我当时带人的经验是原型链这关过不去后面看Vue源码、React源码都是空中楼阁。因为组件继承、mixin合并、插件机制统统建立在原型和对象描述符之上。建议准备笔试的同学把从创建一个空对象到找到Object.prototype上toString方法这个过程用画图的方式自己走三遍。4. 浏览器与网络为性能和安全意识打分4.1 渲染机制从URL输入到页面呈现这类题在2017年的笔试卷里经常作为简答题出现在浏览器地址栏输入一个网址到页面渲染完成中间发生了什么。这道题看似开放实则考的是知识体系的完整度。完整链路是DNS解析出IP地址建立TCP连接发送HTTP请求服务器返回HTML浏览器解析HTML生成DOM树同时解析CSS生成CSSOM树两者合并成渲染树然后执行布局Layout和绘制Paint。如果页面里有JS解析过程中遇到script标签会暂停DOM解析先下载并执行JS所以现代前端会把script放在body底部或者用defer和async属性来控制加载时机。这道题还能延伸出回流Reflow和重绘Repaint的问题。获取offsetWidth、offsetHeight、getBoundingClientRect这些属性时浏览器为了返回准确值会强制同步布局Forced Synchronous Layout也就是把本来要攒在一起批量处理的布局任务提前执行。如果循环里一直做这件事页面性能就会肉眼可见地下降。读属性和改样式要分开把读操作先存进变量集中修改这是我从这份题目里学到的实用技巧。4.2 HTTP缓存命中强缓存和协商缓存的判定逻辑缓存题是2017年笔试里比较有后端味的题考的是前端对网络请求效率的理解。强缓存相关字段是Expires和Cache-Control命中强缓存时客户端直接从本地缓存拿数据不发请求。协商缓存相关字段是Last-Modified/If-Modified-Since和ETag/If-None-Match命中协商缓存时客户端会发请求服务器返回304告诉客户端用缓存响应体不传。有个细节容易被忽略Cache-Control的优先级高于ExpiresETag的优先级高于Last-Modified。因为Last-Modified精确到秒如果文件在同一秒内被改了两次就无法准确判断。ETag用内容哈希或版本号标识能避免这个问题。这道题在2026年的今天依然是前端面试的必考题因为前端性能优化的核心手段之一就是减少请求、利用缓存。你谈性能优化的时候如果连缓存的命中判定都说不清楚那优化方案就是空中楼阁。4.3 跨域与安全主流方案和应用场景跨域问题的根因是浏览器的同源策略协议、域名、端口任何一个不同就视为跨域。2017年的笔试常考解决方案CORS、JSONP、nginx反向代理、postMessage。JSONP的原理是利用script标签不受同源策略限制动态创建script标签通过URL传一个回调函数名服务端返回一段调用这个回调的JS代码。它的局限是只支持GET请求。CORS则需要在服务端加响应头其中Access-Control-Allow-Origin是最关键的字段。预检请求OPTIONS在非简单请求时会发生每次跨域PUT、DELETE、或自定义headers请求前浏览器都会先发一个OPTIONS。Web安全相关的题也经常出现。XSS跨站脚本攻击的核心是把用户输入当成代码执行常见防御是转义输出内容、设置Content-Security-Policy。CSRF跨站请求伪造的核心是浏览器自动携带Cookie导致的身份冒用常见防御是校验Referer、加CSRF Token。这两类题在2026年依然必考而且很多岗位会结合具体的业务场景来问比如如果用户输入框里填了一段script你怎么办。能答出来与能讲清楚层层防御的关系是两种不同的层级。5. 手写代码题笔试环节真正拉开差距的地方5.1 防抖、节流、深拷贝这三兄弟年年见手写防抖是2017年笔试中出现频率最高的一道题没有之一。防抖的含义是事件被连续触发时只有最后一次触发后的等待时间内没有新触发才执行回调。实现思路是利用闭包保存定时器ID。这里有一个容易踩的坑回调函数里的this需要让它在实际调用时指向触发事件的元素。所以不能用箭头函数来包裹最外层箭头函数没有自己的this也不能直接fn()调用丢this。正确做法是在setTimeout回调里通过fn.apply(this, args)调用。args也有讲究需要把事件对象等参数传给原函数所以要用arguments做一次数组转换或者用rest参数。节流的实现方式有两种时间戳版和定时器版。时间戳版第一次触发立即执行停止触发后不会再多执行定时器版在停止触发后会再执行一次。这两种行为差异经常是面试官追问的点要让候选人说出各自的使用场景——比如按钮双击提交要防抖滚动加载要节流定时器版保证最后一次能加载完成。深拷贝在2017年的手写题里要求没那么变态不需要处理太深的循环引用。但基本的递归写法要能写对判断值类型基本类型直接返回、判断数组和对象分别创建、递归拷贝每一层。接下来面试官一定会追问如果对象里有个属性指向自身形成循环引用会怎样这就是要引出WeakMap或者Map来记录已拷贝对象遇到同一引用时直接返回避免无限递归。5.2 手写Promise难度天花板但值得硬啃如果手写题只考防抖节流区分度还不够高。2017年的高分试卷往往在手写Promise这道题上见真章。手写Promise的核心不是把API背下来而是理解状态机pending可以切换到fulfilled或rejected一旦状态改变就不能再变。then方法返回的是一个新的Promise所以需要链式调用。值的传递通过resolve和reject回调来实现异步的兼容性处理通过把回调放入微任务队列或宏任务队列当时很多简单实现用setTimeout模拟来保证。我当时带新人写手写Promise发现一个普遍卡点错误的捕获与传播。很多人不知道then的第二个参数和catch在行为上的区别也不知道then里抛出的异常会被下一个then的reject捕获。这个机制的底层是Promise将异常统一走reject通道只有理解了这个才能写出可靠的Promise.all、Promise.race、Promise.finally。坦白说2026年的校招笔试很少会要求从零手写一个完整的符合Promise/A规范的Promise了但手写一个简化版本依然是很多公司评估候选人编码能力的试金石。它能验证你对异步控制流、状态管理、错误处理的理解深度。所以我还是建议你抽一个周末静下心自己写一遍收获会远超预期。5.3 编程题里藏着的数据结构与算法意识除了手写函数2017年这份卷子里还有几道偏向算法的小题比如数组去重、字符串反转、找出数组里出现次数最多的元素。这类题通常不考高深的算法复杂度分析而是看候选人能不能写出简洁可靠的高质量代码。数组去重就有好几种思路用Set一行搞定、用filter配合indexOf、用对象做哈希表。如果数组里既有数字又有字符串回答时要考虑是否需要区分类型1和1算不算相同。这些细节往往比主逻辑更能看出一个人的工程素养。在校招笔试的语境下算法题的定位是确保候选人具备基本的逻辑拆解能力 不是筛出ACM大神。所以准备时不用陷入题海把常用数据结构数组、对象、Set、Map的API和各自的时间复杂度搞清楚再配合十道经典题练习就够用。6. 站在2026年回望这份卷子最大的价值不是题目是出题思路6.1 什么变了框架普及让知识边界整体抬高了2017年前端面试考察的关键词是扎实。2026年考察的关键词变了变成了体系化。因为基础知识本身有了更大范围的变化ES6的新特性全面普及Promise、async/await、可选链、空值合并、BigInt等已经成为日常语法的一部分浏览器能力大大增强工程化深度也不可同日而语。所以同一个知识点现在面试官会问得更深。比如闭包2017年问这个循环输出什么2026年可能会追问闭包会不会造成内存泄漏如何排查。比如HTTP缓存现在会跟Service Worker的缓存策略结合起来问。比如手写防抖节流现在还会问如果回调里是个async函数要不要处理竞态问题。但反过来说很多2017年需要死记硬背的知识点在2026年已经不需要手动写了。比如手动处理CSS浏览器前缀现在有PostCSS的autoprefixer比如手动做模块打包的若干配置现在有Vite开箱即用。框架和工具的演进把这些底层细节封装掉了但笔试考查的核心能力——能否把原理讲清楚、能否在工具失效时自己排查——反而更突显了。6.2 什么没变底层原理和人脑的认知方式没变JS的事件循环机制没有变原型链的委托关系没有变HTTP协议里缓存的判定逻辑没有变浏览器的同源策略没有变。这些底层的稳定知识构成了前端这个领域真正值得长期投入的部分。我见过不少准备面试的同学把大量精力花在背诵新框架的新语法上结果被一道闭包题问倒。这说明他们把面试准备理解成了信息收集而不是能力建设。翻看2017年这份试卷的意义恰好在于提醒你凡是能靠搜索引擎快速找到答案的知识都不是面试的重点面试的重点是那些需要你在脑子里真正建立起模型的知识。前端社区里有句调侃面试造火箭工作拧螺丝。从某种角度看不无道理笔试里很多东西确实日常开发用不到。但换个角度想造火箭的过程逼迫你建立系统性的认知框架这比上来就拧螺丝却不知道螺丝钉为什么要这么设计还是要强得多。校招阶段企业本就不指望你直接上手做项目考察的是你的学习路径、思维方式和可塑性这恰恰是笔试真正的价值所在。6.3 从刷题到构建知识体系的备考路径复盘完这份2017年的试卷我想给正在准备前端校招的同学一套自己的方法这套方法这些年带过不少新人反馈还不错。第一步把知识点按层次拆成语言基础、浏览器原理、网络协议、框架体系、工程化几个大块每个大块再细化出核心考点。不要用碎片化的刷题APP来建立主框架刷题适合查漏补缺不适合从零搭体系。第二步针对每个核心考点写一篇讲给别人听的小笔记。用费曼学习法的核心逻辑如果你不能把这个概念讲得让一个非技术背景的人听懂说明你没有理解到位。这一步很费时间但它能一次性把知识固化成长期记忆。第三步手写代码题统一归档。把防抖、节流、深拷贝、Promise、事件总线这五件套练成肌肉记忆最好是脱离IDE的纯手写。写的速度不重要重要的是不留语法死角。我见过有人面试现场手写防抖把function写错成funciton这种低级失误太亏了。第四步面试前做一次场景化自测把你学过的每个知识点都挂到一个真实业务场景上。例如讲Object.defineProperty时要联想到双向绑定的实现讲闭包时要联想到模块化封装讲事件代理时要联想到长列表的性能优化。有了场景挂载面试官问你的时候你就不只是背答案而是陈述解决方案。7. 面试场上那些不能写在笔试卷上的建议翻完这份2017年的笔试卷除了技术题目本身我还想聊几个容易被忽略的软性层面因为我在面试候选人时见过太多笔试高分、现场翻车的案例了。第一个是审题习惯。很多人笔试题失分不是因为不会而是因为没看清题目要求就动手写。比如题目要求手写一个防抖函数要求第一次点击立即执行你没看清楚直接写了常规版一下就丢了分数。我的建议是答题前先把题目里的限定条件圈出来尤其是是否立即执行是否处理this是否需要取消这些关键词。一道题如果因为审题不清而失分是最冤枉的扣分方式。第二个是代码规范感。校招笔试卷子的字迹不要求漂亮但代码风格要清晰。变量名用有意义的英文单词不要用a、b、c函数内部的逻辑分段要清晰加适当的空行和注释。很多笔试题是按点给分的阅卷人一天要看几十份卷子一个清爽的代码排版本身就能带来印象分加成。第三个是调试过程的呈现。手写代码难免有疏漏但一份好的笔试卷即使在答错的情况下也要让阅卷人看到你的思考路径。比如用注释写出这里需要考虑闭包保存变量这里需要补一个边界判断这种描述哪怕最后的代码不完整阅卷人也会觉得你有良好的编程素养。相反如果留白一片哪怕思路是对的阅卷人也看不见。第四个是面试时的不会策略。笔试遇到完全没思路的题不要空着不写至少把相关的知识点和已知的分析框架写上去。比如看到一道关于性能优化的大题你哪怕不知道确切的底层实现也可以从减少请求、减少DOM操作、利用缓存、拆分任务这几条主线出发来答。面试官想看的往往不仅是一个标准答案而是你在面对未知问题时的分析框架和分析路径。我2023年带过一个实习生笔试分数一般但面试时有一个细节让我印象很深被问到一个不了解的API时他没有直接说不会而是说这个API我没用过但如果让我来设计我会从xxx角度考虑它的用法。这种基于逻辑框架进行未知推导的能力在我这里比死记硬背十个API都加分。笔试和面试的底层逻辑是一致的——不是考你背过多少而是考你面对没见过的题目时能不能用已有的知识结构推演出合理的解答路径。七年过去挖财这份2017年的校招前端笔试题在网络上的讨论热度早就退了但它的出题思路依然值得拿来做学习参照。它告诉我一个道理在这个技术迭代如此之快的行业里真正值得投入时间去啃的永远是那些一旦学会就不会轻易过时的底层知识。如果你最近在准备前端面试与其焦虑地刷二十套最新题库不如先静下心把这份试卷里考察的知识点逐个画成自己的知识图谱。这份沉下来构建体系的功夫比任何一道题的答案都值钱。