ARTICLE DETAIL

资讯详情

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

从2017年同程前端笔试题看校招面试的变与不变

从2017年同程前端笔试题看校招面试的变与不变 两年前整理电脑文件时翻出一份同程2017年的校招前端笔试试卷当时自己的批注还留在上面。那次笔试我记得很清楚题目不算偏但覆盖面很广从基础的HTML/CSS到JavaScript闭包原型链再到浏览器缓存和跨域方案最后还有一道算法题。当时因为一道事件循环的输出顺序题纠结了很久结果最后面试环节面试官也追着那道题问了我十分钟。这几年陆续以面试官身份参与过校招出题和评审回过头再看这类试卷越发觉得其中很多考察点并不过时只是换了一种问法继续出现在今天的前端面试里。这篇文章想和你一起复盘这份试卷的完整考点并结合我这些年实际做项目和面试候选人的经验聊一聊哪些题目值得认真对待哪些题目背后的设计思路才是真正的考察目的。不管你是在准备校招还是已经工作两年想梳理基础这篇文章应该都能给你一些参考。1. 2017年同程前端笔试试卷的卷面结构与考察逻辑1.1 整份试卷的题型分布与时间压力先还原一下这份试卷的大致结构。整张卷子满分100分考试时间90分钟题型分为四块选择题约15题每题2分共30分覆盖HTML/CSS/JavaScript基础、浏览器、网络协议。填空题约10题每题2分共20分偏重概念记忆和代码输出结果。简答题4题每题5分共20分需要手写代码或简述原理比如事件代理、闭包的作用、跨域解决方案。编程题2题每题15分共30分一道是数组去重和排序一道是DOM操作相关的功能实现。90分钟做完全部题目时间其实非常紧张。选择题基本要求一分钟之内出答案填空题考验的完全是记忆的准确度简答题和编程题则需要比较扎实的手写代码能力。我在实际监考和批改试卷时发现很多考生前面选择题做得不错但到编程题就直接空着。原因倒不是完全不会写而是时间分配出了问题——前面简答题写得太详细每道题都恨不得把原理从头讲到尾等做到编程题的时候只剩下二十分钟。所以这张卷子的第一个隐藏考点其实是时间管理你能不能识别哪些题值得深写、哪些题点到即止。这个能力放到今天的前端面试同样重要特别是在两小时的机试限时环节里合理的做题顺序往往比多掌握一个冷门API更有实际价值。1.2 这份试卷在当年前端招聘里所处的位置2017年正好处在前端行业的一个分水岭。React已经发布了16版本Vue 2.x 也已经火了一年多但很多学校的课程里教的还是 jQuery 那一套大多数应届生简历上写的都是熟悉jQuery、Bootstrap了解AngularJS。同程这类OTA在线旅游公司业务特点是页面多、交互密集、需要大量活动页和H5页面支撑运营需求。所以校招笔试的考察思路很明确不追新框架更看重基础是否扎实、能否快速上手业务开发。这也解释了为什么这份试卷里几乎没有React或Vue相关的题目。倒不是说这些技术不重要而是那个阶段校招的核心目的是筛选可培养的苗子——框架可以入职后再学但JavaScript语言特性、浏览器工作原理、网络基础这类知识靠短期突击很难真正理解透。这个逻辑放到今天依然成立。虽然现在的前端面试必问框架源码、工程化、性能优化但很多公司在校招第一轮仍然会先用基础题过滤一遍候选人。我见过不少简历上写着精通Vue的同学问他flex布局和float布局在实际项目中你怎么选型反而说不清楚。基础这关永远绕不过去。2. 基础三件套考点复盘HTML/CSS/JavaScript各自问到了什么深度2.1 HTML部分语义化不是口号是实实在在的页面结构能力试卷里HTML相关的选择题大概有3-4道主要围绕语义化标签、表单元素和HTML5新特性展开。有一道题我记得很清楚给出几个标签让选择哪些是HTML5新增的语义化标签。选项里有header、nav、div、section、aside、span。这道题的陷阱在于section——它不是像div那样的纯容器而是带有主题意义的内容区块但很多教材里并没有强调这一点导致很多考生把section标成了不确定或者干脆漏选。另一道比较有意思的题是考察label标签的两种关联方式一种是用for属性指向输入框的id另一种是把输入框嵌套在label内部。这道题本身不难但它背后的实际场景是表单可用性。我在写活动页时经常遇到表单校验报错信息要点击才能聚焦输入框的需求如果HTML结构里没有正确使用label这个交互就得靠JS手动绑定事件麻烦不少。填空题里还考了>function createCounter() { let count 0; return function() { count 1; return count; }; } const counter createCounter(); counter(); // 1 counter(); // 2这道题考察的不只是闭包的语法而是闭包能保存变量的核心特性。如果候选人对闭包的理解停留在函数里面返回函数这个层面那他在真实项目里很可能写出内存泄漏的代码——比如在setInterval里无脑挂载闭包函数或者在一个长列表循环里反复创建匿名函数导致每次渲染都丢失DOM事件绑定。原型链的考察方式是一段代码输出题定义了构造函数和实例然后问instance.hasOwnProperty(xxx)和xxx in instance的区别。前者只看实例自身属性后者会沿着原型链查找。这道题背后考察的是对JavaScript继承机制的理解也是后来面试官追问的重点。事件循环方面2017年的试卷考的是setTimeout、Promise的执行顺序但当时的Promise还不是面试主流更多是考setTimeout嵌套的时间计算。放到现在的标准看事件循环的考察已经升级到微任务、宏任务、requestAnimationFrame执行时机等更细的维度但基础逻辑没有变理解JavaScript是单线程的理解同步代码先执行、异步回调按队列顺序执行。2.4 当年高频出错题typeof null 与 instanceof 的关系填充题里有一道非常经典又坑人的题typeof null的输出结果是什么。答案是object但这个结果其实是JavaScript语言设计上的一个历史bug。很多考生记住了答案但不知道这个bug是怎么来的——在JavaScript最初实现中对象类型的类型标签是0而null表示空指针在底层也是0所以typeof null就误判成了object。我在这里展开讲一下因为这道题体现了一种面试态度你只是背了答案还是真正理解语言的设计和缺陷。今天的面试官同样喜欢问这类反直觉问题比如[] ![]的结果为什么是true或者0.1 0.2 ! 0.3是因为浮点数精度问题。这类问题的价值不在于那个输出结果而在于候选人是否具备从语言规范层面去分析问题的能力。3. 浏览器与网络知识分值不高但区分度最高的部分3.1 HTTP状态码与前端缓存策略试卷里有一道选择题列出几个HTTP状态码让选择哪个表示永久重定向哪个表示临时重定向。正确答案是301永久、302临时。这道题放到2026年来面试我会追加一个问题什么时候用301什么时候用302如果网站域名从http切换到https你希望搜索引擎和设备端把旧地址永久导向新地址就用301如果只是临时维护页面希望用户在维护结束后继续访问原链接就用302。更有区分度的是缓存策略的考察。试卷里问到Cache-Control和Expires的区别答案是Expires返回的是绝对时间如果客户端本地时间和服务器时间不一致就会出现缓存失效的问题Cache-Control里的max-age是相对时间以浏览器发起请求的时间为基准不会受时钟偏差影响。既然Cache-Control更可靠为什么还有Expires存在因为老版本浏览器不支持Cache-Control做降级兼容时需要同时携带两个头。还有一类关于协商缓存的题ETag和Last-Modified的区别。Last-Modified的粒度是秒级如果文件在极短时间内被修改了两次Last-Modified可能感知不到ETag是基于文件内容生成的哈希值能精确感知内容的变化。两种机制通常配合使用浏览器发起请求时同时携带If-Modified-Since和If-None-Match服务器端优先校验ETag一致则返回304不一致则返回200和新的资源。这套知识在校招层面的考察并不多但真正参与过线上性能优化的前端都应该烂熟于心。3.2 输入URL到页面展示中间发生了什么简答题里有一道描述在浏览器地址栏输入一个URL并回车后发生了什么这道题现在看起来已经是前端面试的传统艺能了但2017年时还不算烂大街。这道题考察的是候选人对整个Web链路的完整认知从DNS解析、TCP连接、TLS握手、HTTP请求、服务端处理、响应返回、浏览器解析HTML、构建DOM树、加载CSS和JS、渲染页面再到关闭连接。我当时批改试卷时发现一个规律能完整写出DNS解析和TCP三次握手的考生很多但能把浏览器渲染过程说清楚的很少。很多人知道DOM树和CSSOM树合并成渲染树但不知道为什么会有DOMContentLoaded和load两个事件也不知道JS脚本放在body底部和用defer/async加载的区别。这样一个题目其实有层次之分。初级回答输入URL、DNS解析、发起请求、拿到HTML、解析渲染。中级回答会把缓存策略也加进去先查浏览器缓存命中就直接用不发起网络请求。高级回答则会把现代浏览器的渲染流水线也纳入讨论——HTML解析、样式计算、布局、绘制、合成以及每个阶段可能的优化点。3.3 跨域问题的三种主流解法跨域是当年简答题的必考内容今年仍然是。2017年时主流方案是JSONP、CORS和反向代理nginx层转发现在则多了postMessage和WebSocket这些场景化的方案。我比较建议用什么是同源策略来切入回答。同源策略是浏览器出于安全考虑提供的机制它限制一个源的文档或脚本与另一个源的资源进行交互。所谓同源是指协议、域名、端口三者一致。JSONP的原理是script标签不受同源策略限制所以可以通过动态插入script标签来加载跨域接口返回的JS脚本。但它只能发GET请求而且它本质上是在执行一段远程代码安全性需要靠服务端保证。CORS则是服务端在响应头里加Access-Control-Allow-Origin告诉浏览器这个请求是被允许的。现在的主流方案基本就是CORS配合withCredentials来处理携带Cookie的情况。如果问为什么不用JSONP来请求POST接口这个问题能区分出候选人是不是真的理解了JSONP的原理而不是只知道这个名词。试卷里这个问题出现在简答题批改时我看到最多的情况是候选人写出了JSONP原理但没有提到它只支持GET请求。这是个很典型的细节盲区。4. 框架与工程化2017年考得不深但可以看出你是否具备现代前端意识4.1 当时的框架题jQuery 依旧在MVVM 刚露头这份试卷的框架相关考察并不难主要是jQuery的选择器和事件绑定方式。有一道填空题是写出$(document).ready(function(){})和window.onload的区别答案是前者在DOM树构建完成后就执行后者要等页面所有资源包括图片、样式、脚本都加载完才触发。这个考点放到今天也是有用的因为理解页面加载阶段的不同事件执行时机是做性能优化和首屏渲染方案的基础。值得一提的是试卷里有一道开放性的简述题谈谈你对前端框架的理解。这个题没有标准答案批改时主要看候选人能不能说清楚框架解决的问题。当时比较优质的回答会提到数据驱动视图——不需要手动操作DOM通过数据变化自动更新UI组件化——页面拆分成可复用的独立单元状态管理——复杂应用中数据和视图的一致性维护。如果能提到虚拟DOM的性能优化思路基本就是这批候选人里的头部水平了。放到2026年来看这个开放性问题的考察逻辑依然适用。只是谈谈你对前端框架的理解在今天会更倾向于追问具体框架的源码实现比如Vue的响应式原理、React的fiber调度、组件通信方式等。但底层逻辑没变你在用一个框架你要知道你用它来解决什么问题它帮你省掉哪些工作它又引入了哪些新的复杂度。4.2 工程化萌芽模块化与构建工具的初步考察2017年时前端工程化已经萌芽但校招笔试对这块的考察非常基础只考了模块化的几种方案AMD、CMD、CommonJS、ES6 Module。很多考生知道ES6 Module是标准但说不清楚它和CommonJS的关键区别——ES6 Module是编译时静态分析可以做到依赖静态解析支持tree-shakingCommonJS是运行时加载模块导出的对象是值的拷贝而不是引用。实际开发中这个区别带来的影响很直接如果你在一个循环里动态require模块CommonJS允许但ES6 Module不行它的import必须放在顶层。反过来ES6 Module因为静态分析可以做tree-shakingCommonJS则不行。这些知识点在今天的前端构建优化里依然是核心概念只是换了问法比如打包出来的代码里为什么会有死代码没有被移除。构建工具的考察只停留在概念层面问了webpack是干什么用的。答案是好理解模块打包、资源处理、开发服务器、代码分割。但如果今天面试再问webpack我大概率会追加一个追问webpack的loader和plugin有什么区别loader负责对特定类型的文件进行转换比如sass-loader把SCSS编译为CSSbabel-loader把ES6编译为ES5plugin则是在webpack构建流程的特定节点执行更复杂的任务比如HtmlWebpackPlugin在打包完成后生成HTML文件。4.3 从同程的业务场景推测考点背后的意图同程作为OTA公司前端业务场景里大量涉及列表页、详情页、下单流程和多端适配这类需求。所以试卷里有一道很贴近业务的题一个页面里有多个相同结构的列表项如何给每一项绑定事件可以做到性能最优。这题考的就是事件代理。当时写答案的思路是利用事件冒泡在父容器上统一监听click事件通过event.target判断点击的具体是哪个子元素再做对应处理。这样做的好处是减少内存占用不需要给每个子元素都绑定事件、动态添加的子元素不需要额外绑定事件。这道题看起来简单但我后来在面试里经常把它升级成为什么要用事件代理来考察候选人的性能意识。如果候选人能答出动态列表在初始化时为空等数据返回后再渲染节点如果用循环绑定事件每次渲染都要先解绑再绑定不仅麻烦而且容易造成内存泄漏这个层面那他大概率是理解这个问题本质的。这道题放到今天的价值依然很高。现在很多React/Vue应用里开发者直接在组件里写onClick{() handleClick(item)}并不会意识到这个写法在长列表里会创建大量匿名函数导致内存占用上升和渲染性能下降。虽然现代框架在虚拟DOM层面做了很多优化但这个性能问题本身并没有消失。5. 算法与逻辑题校招笔试的硬骨头也是面试追问的重灾区5.1 数组去重与排序的多种解法编程题第一题是给一个数组要求去重并按从小到大排序。这道题不限定算法也不限定语法给了很大的自由发挥空间。我批改时看到三种主流写法第一种是ES6的Array.from(new Set(arr))简洁且正确但也会暴露一个问题——考生如果只写过这种方法让他现场换个思路比如用双指针或者filter就会卡壳。所以题目后面还有一个追问如果不用Set你会怎么写第二种是filter indexOf组合arr.filter((item, index) arr.indexOf(item) index)。这种写法能工作但时间复杂度较高数组是修改过的每次indexOf都要遍历一次原数组。如果数组长度在万级别这种写法会明显卡顿。第三种是对象键名法用一个对象来记录已经出现过的元素。这个方案在ES5时代非常流行但有一个坑如果数组里同时存在数字1和字符串1它们会被当作同一个键导致去重错误。所以要配合typeof加类型前缀。能把这个坑说明白的候选人说明他真的动手调试过细节。排序方面直接调用arr.sort((a, b) a - b)是最常见的写法但有些考生不知道sort默认的排序规则是按字符串UTF-16码元比较的所以[10, 9, 8].sort()得到的是[10, 8, 9]而不是[8, 9, 10]。这个看似简单的知识点正好能区分出候选人有没有踩过这个坑。5.2 手写一个防抖函数编程题第二题是手写一个防抖函数。这在当年已经算比较贴近实际开发的题目了。防抖debounce和节流throttle的区别是防抖是事件停止触发后的一段时间内没有新事件才执行节流是固定时间间隔内最多执行一次。我当时写的是function debounce(fn, delay) { let timer null; return function(...args) { clearTimeout(timer); timer setTimeout(() { fn.apply(this, args); }, delay); }; }要注意的是fn.apply(this, args)这里为什么用this。因为返回的函数是被调用时内部this应该指向调用它的那个对象比如button.addEventListener(click, debounce(handleClick, 300))绑定事件后回调函数里的this指向button元素如果这里不把this绑定进去回调函数里的this就会变成undefined严格模式或window。除了防抖面试官也常常追问节流以及两者各自适合的场景。防抖适合搜索框输入联想、窗口resize后停止调整再计算节流适合滚动事件里的无限加载、拖拽时的位置更新。每道算法题都要配套能落地的场景不然面试官容易判断你只是背了代码模板。5.3 逻辑题不只是考聪明也考沟通思路试卷最后还有一道逻辑题类似有一个天平和一个已知重量的砝码如何在若干次称量中找出唯一一个重量不同的球。这类题目没有标准解题过程面试官看重的是候选人如何拆解问题、如何在信息不完整的情况下提出合理的假设。这种题在笔试里的作答质量很能看出一个人的思维方式。优秀的答案会把问题抽象成用尽量少的比较次数找出异常元素然后设计决策树。普通的答案会从心算开始穷举。空白的答案说明候选人遇到没见过的题容易直接放弃这也是一种信号——实际工作中你遇到的很多问题都不是教科书原题能不能在压力下保持分析能力才是关键。现在的前端算法面试已经更倾向于LeetCode风格的数据结构与算法题但这道逻辑题的位置依然有意义它提醒我们笔试题可以考察的不只是知识点还可以观察解题过程本身。6. 从2017年的试卷看今天的面试哪些考点会变哪些底层逻辑不会变6.1 已经过时或边缘化的考点时代的痕迹在这份试卷里很明显。jQuery相关的内容今天基本不会再出现在校招笔试里了除非少数老项目维护岗还在用。AMD、CMD模块化规范也被ES Module和打包工具彻底取代现在的候选人打开webpack配置看到require的时候对CommonJS还有印象已经算基础扎实了。width和height解析盒模型的考法也在变。过去面试必问box-sizing: border-box和content-box的区别现在这道题的存在感已经降低因为主流样式方案里border-box基本是全局设置的默认选项。但换个角度说正因为它是默认选项很多候选人反而不理解它解决了什么问题——如果面试官追问为什么现在默认用border-box很多人说不出因为它能让padding和border包含在设定的宽高内更容易实现预期布局效果。6.2 至今仍活跃在面试一线的核心考点像事件循环、闭包、原型链、跨域、性能优化、模块化这类基础知识点到今天依然是前端面试的核心盘。只是问法更灵活了从解释什么是闭包变成了这段代码里闭包导致的问题是什么怎么解决从说一下跨域的解决方法变成了这个线上页面为什么请求被拦截了你会从哪些方面排查。这种变化本质上是在考察一个更底层的迁移能力从背诵知识点到运用知识解决实际问题。2017年的试卷里描述URL输入到页面展示全过程是一道简答题今天的面试里它可能被揉进一个更高层次的追问链为什么这个页面首屏资源在弱网环境下要拆成两份加载这涉及到TCP拥塞控制、HTTP/1.1的连接限制、CDN回源耗时、服务端渲染拆包策略等综合知识。所以我的建议是不要只刷最近一年出现的面试题。把2017年这份老试卷里的基础题认认真真啃一遍再往后延伸思考这个知识点在什么时候会出问题出问题了怎么排查这种复习的深度远比刷十遍八股文更有底气。6.3 我作为面试官会怎么用一套基础题来判断候选人这几年我参与校招评审时一般会用一套组合拳来考察候选人大致思路是这样笔试阶段基础题筛掉完全没有动手写过代码的简历选手技术面第一轮会从笔试错题切入看候选人能不能现场复盘自己当时的思路并纠正第二轮会结合一个实际业务场景让候选人现场设计方案比如列表页筛选功能怎么做涉及哪些性能考虑终面则看软素质、学习能力和团队协作意愿。这套流程里最核心的原则是笔试的分数不是目的分数背后的思考过程才是。一道考察事件委托的选择题两个人同样做对了但一个是因为在项目里真的遇到列表渲染性能问题主动做了优化另一个只是背过事件代理能提升性能这个结论。这两者在面对后续追问时的表现会天差地别。所以我在批改试卷时往往更关注那些虽然结论错误但推导过程里有合理假设的答案——这种候选人往往只是缺一个正确的上下文但分析框架是对的培养起来会很快。6.4 从基础题到架构思维的延伸如果只把这份试卷的价值停在刷题层面那格局就小了。它其实反映了前端面试的一个稳定趋势基础决定下限思维决定上限。先看基础决定下限。一个候选人如果连flex布局都写不利索连Promise.all和Promise.race都分不清那把他招进来后他看到现在的复杂业务界面光是处理样式问题就会耗费大量时间更别提让他独立负责一个模块。基础扎实意味着他不需要在琐碎问题上频繁求助同事和导师可以聚焦在更高层次的设计指导上。再看思维决定上限。一个候选人即使基础稍弱但如果他能从一道数组去重的题延伸出时间复杂度、空间复杂度、边界条件、哈希碰撞、类型转换这些分析维度那他大概率是个值得培养的好苗子。因为前端这个行业演进速度极快今天的主流框架几年后可能就变成历史产物真正留下来的是你分析和解决问题的能力。从这份2017年的试卷来看今天的前端面试并没有抛弃这些基础考察只是把它们包装成了更复杂的业务场景。不管你是准备踏入前端的新人还是工作几年想往上走的进阶者把这份试卷当作一面镜子对着它检验一下自己的知识体系是否还有盲区是很有价值的动作。7. 复盘完这套试卷后我的一些实操建议7.1 给正在准备前端校招的同学怎么高效利用老试卷老试卷最有价值的地方在于它能帮你快速搭出一个知识框架。拿到一份试卷后我建议先别看具体题目自己先画出这个岗位需要掌握的知识地图再对照试卷的考点去补漏。以这份2017年同程试卷为例基本知识地图应该是HTML语义化、表单、HTML5新特性、可访问性。CSS选择器、盒模型、布局浮动、定位、flex、grid、响应式、动画。JavaScript数据类型、作用域、闭包、原型链、异步回调、Promise、async/await、事件机制、DOM操作。浏览器与网络HTTP协议、缓存、跨域、渲染机制、性能优化。框架理解至少一个主流框架的核心思想。工程化模块化、打包工具、代码规范、测试。算法与数据结构数组、字符串、链表、树、排序、动态规划以及至少能手写常见的前端工具函数。对着这张地图把每一块的知识点都过一遍再去找对应的笔试题练习效率比盲目刷十套试卷要高得多。7.2 给工作两三年想跳槽的前端基础常看常新很多有工作经验的前端容易陷入框架源码看得飞起但基础概念反而模糊的状态。我在面试一些工作两三年的候选人时经常遇到简历上写着精通性能优化但问到浏览器缓存时只会说浏览器自动缓存了的人。如果你属于这种情况建议每半年做一次基础复盘。不用大块时间像下面这种方式就很有效每周抽半天时间写一两个手写题数组去重、防抖节流、深拷贝、Promise实现、instanceof实现。把常用HTTP状态码200、204、301、302、304、400、401、403、404、500、502、503的含义和出现场景再过一遍。打开Chrome DevTools的Network面板和Performance面板重新分析一次自己的项目资源大小、加载顺序、阻塞原因、缓存命中情况。这些东西看起来基础但它们才是你做性能优化的底层依据。你不理解304 Not Modified是怎么触发的看到线上304就会以为请求出错了接着就往错误的方向排查浪费大量时间。7.3 给面试官的一个建议从错题里看思维而不是只看对错如果你也参与前端校招出题或评审我想分享一个这几年实践下来的感受批改试卷时减少对错二分法多关注候选人写下的推导过程。比如一份试卷里候选人在编程题里用filter indexOf实现了数组去重虽然没有用上ES6的Set但代码逻辑清晰、变量命名规范还在注释里说明了时间复杂度。这类候选人实际工作上手速度往往比那些背了一个标准答案但一问三不知的候选人快得多。反过来如果候选人所有题都答对了但问到他项目里遇到的问题是怎么排查时支支吾吾那他在实际工作中的表现未必理想。笔试只能考察你知识点的覆盖度真正决定职场表现的是把知识用出来的能力。近年来我在技术社区里看到很多前端面试八股文汇总之类的资料有人同意有人反对。我的态度是与其说八股文没有价值不如说它的价值在于帮你建立知识索引而真正的理解必须靠你自己在项目里反复验证。就拿闭包来说你看了十个闭包是什么的文章不如自己去写一个会导致内存泄漏的组件然后在排查过程中真正理解它背后的引用关系。这份2017年同程前端笔试给我最大的启发是无论技术和框架怎么迭代对一个合格前端工程师的要求里扎实的计算机基础 清晰的逻辑思维 能落地的工程能力这三个维度一直没有变。变的是考察方式不变的是底层能力。希望这篇复盘能给你带来一些不一样的角度也欢迎你在评论里聊聊最近一次前端面试里让你印象深刻的题目。
返回列表