ARTICLE DETAIL

资讯详情

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

腾讯音乐前端笔试复盘:核心考点、算法题与备考建议

腾讯音乐前端笔试复盘:核心考点、算法题与备考建议 春招季向来是前端岗位竞争最激烈的时候腾讯音乐的笔试算是其中很有代表性的一个。我参加了2023年春招第二批前端开发岗的笔试整个过程下来感受挺深题目覆盖面广、基础考察细、部分题目有明显区分度。趁着记忆还热乎把这次笔试的题型结构、核心考点和复盘心得整理出来给准备冲大厂前端岗的朋友做个参考。1. 笔试整体结构与考查方向1.1 题型分布与时间分配整场笔试时长120分钟题量适中但时间并不宽裕。我遇到的题型大致分为四类计算机基础选择题、JavaScript/前端专项选择题、算法编程题、简单问答题。选择题占了大概60%的比重算法题两道问答题两道。从分值分布来看选择题和算法题是拿分大头问答题属于拉开差距的环节。时间分配上我建议这样选择题控制在45分钟左右算法题每题25分钟问答题每题10分钟最后留10分钟检查。实际考下来这个节奏比较合理。如果某道选择题卡住超过2分钟果断跳过先把有把握的分拿到手。1.2 考点覆盖范围复盘从整张卷子的考点分布来看考察最密集的依然是JavaScript基础尤其是闭包、原型链、this指向、事件循环这几块。其次是CSS布局和浏览器渲染原理框架相关题目不算多但出现了一道Vue响应式原理的题目。网络协议和前端工程化也各有涉猎。这里有个很重要的信号大厂前端笔试的重心一直在往**基础深度 工程实践**这个方向倾斜。单纯背面试题已经不够用了考察的是你在真实项目中积累的理解深度。比如有一道关于浏览器缓存的题表面问的是Cache-Control和Expires的区别但实际考察的是你能否说清楚强缓存和协商缓存的完整流程。2. 核心知识点详细拆解2.1 JavaScript基础闭包、原型链与this指向这次笔试的JS选择题中闭包和原型链相关题目占了将近三分之一。有一道题特别典型考察的是闭包中变量引用的陷阱for循环中用var声明变量内部函数输出循环变量值。这个场景相信大家都踩过坑正确答案是全部输出循环结束后的值。要真正理解这道题关键在于明确闭包捕获的是变量的引用而非值。var声明的变量是函数作用域循环结束后i已经变为最终值所有闭包函数访问的都是同一个i。解决办法不外乎三种用let声明、用立即执行函数传参、或者用Function.prototype.bind绑定当前值。原型链部分考了一道很有意思的题目给定一段继承代码判断实例属性访问的输出顺序。这道题实际上考察的是原型链的查找机制——先找自身属性再沿着[[Prototype]]链向上逐层查找。如果对prototype和__proto__的区别不够清晰很容易在这道题上丢分。this指向的问题也是高频考点。我在准备时总结了一个简单粗暴的判断方法看函数调用方式。普通函数调用时this指向全局对象严格模式下是undefined对象方法调用时指向该对象new调用时指向新创建的实例call/apply/bind调用时指向手动指定的对象。箭头函数比较特殊它的this词法绑定在定义时就确定了与调用方式无关。2.2 事件循环与异步编程事件循环的题目这次出了一道比较综合的给出一个包含setTimeout、Promise、async/await的代码片段要求写出输出顺序。这类题目考察的是对宏任务和微任务执行机制的理解。我建议用一个朴素的模型来理解事件循环同步代码先执行完毕然后每轮事件循环从宏任务队列头部取出一个任务执行执行过程中产生的微任务会在当前宏任务结束后立即清空。Promise.resolve().then()和async函数中await后面的代码都会进入微任务队列而setTimeout的回调进入宏任务队列。要注意的是await本质上相当于Promise.resolve().then()的语法糖await之前的代码同步执行之后的代码微任务执行。还有一个容易忽略的细节脚本本身也算一个宏任务所以第一轮事件循环时脚本执行完后紧接着才执行初次产生的微任务。先执行微任务队列再渲染页面这是浏览器保证一致性的机制。2.3 事件机制与DOM操作事件机制考察了一道事件委托相关的题目要求判断事件冒泡和目标阶段的区别。这里要区分三个常考的概念target实际触发事件的元素、currentTarget正在处理事件的元素也就是绑定监听的元素、relatedTarget事件相关的辅助元素。代码中常用事件委托父元素通过判断target来区分操作的具体子元素就是为了让动态添加的子元素也能复用监听逻辑。DOM操作的题目偏向于考察性能优化方面有一道关于批量添加节点应该用DocumentFragment还是多次appendChild的题目。本质上是在讲减少回流Reflow次数对页面性能的影响。实际开发中除了DocumentFragment还可以用display: none暂时隐藏元素再操作或者用requestAnimationFrame合并样式修改这些都是减少重排的有效手段。2.4 CSS布局与样式细节CSS布局考了一道经典的flex布局题实现一个两栏布局左侧固定宽度200px右侧自适应填充剩余空间。这道题用flex: 0 0 200px配合右侧flex: 1可以轻松解决。但笔试中考察的难点在于理解flex属性三个值的含义——flex-grow、flex-shrink和flex-basis分别控制项目的放大、缩小和初始尺寸。有一道BFC块级格式化上下文的题目也比较有意思考察的是BFC如何解决外边距合并问题。实际考察场景就是父元素和第一个子元素之间出现了多余间距问怎么处理。常见触发BFC的方式有overflow: hidden、display: flow-root、position: absolute等。盒模型的计算也是高频题。这里一定要分清标准盒子模型和怪异盒子模型IE盒模型的区别。box-sizing: content-box时width只包含内容区box-sizing: border-box时width包含内容区、内边距和边框。实际项目里大家普遍会设置全局border-box但如果题目没有明确计算时要格外小心。2.5 浏览器缓存机制缓存相关的题目出现在选择题中问的是ETag和Last-Modified的区别以及优先级。这里的关键点是ETag优先级高于Last-Modified。原因在于ETag是基于内容生成的哈希标记能够精确判断资源有没有变化Last-Modified只精确到秒存在内容变但时间没变的可能。强缓存字段Cache-Control和Expires也考了一问重点在Cache-Control: max-age和Expires同时出现时max-age生效。因为Expires是HTTP/1.0时代的产物存在客户端时间和服务器时间不一致的问题所以现代项目都以Cache-Control为准。我还想多说一句缓存这块的知识在实际项目里非常实用。配置不当会导致两种明显的问题——改完代码线上不生效或者HTML被缓存导致页面白屏。面试官考这些点本质上是在筛选有真实线上调试经验的人。2.6 网络协议基础网络协议题目考了HTTP/2的头部压缩和多路复用。这个问题如果只看概念很难说清楚举个直观的例子HTTP/1.1是流水线作业一个请求的响应必须等前一个请求处理完才能开始实际上浏览器会开启多个TCP连接来缓解这个瓶颈HTTP/2多路复用把一个TCP连接切成多个流不同请求的响应可以交错传输互不阻塞。头部压缩则是用HPACK算法在客户端和服务端维护一个静态表和动态表用索引代替重复传输的头部字段。另外还考了一道跨域相关的选择题问的是CORS预检请求OPTIONS请求触发条件。这里要注意不是所有跨域请求都会触发预检。简单请求如GET、POST且Content-Type为application/x-www-form-urlencoded、multipart/form-data、text/plain之一不会触发预检非简单请求才会先发OPTIONS预检确认服务器允许后再发实际请求。2.7 Vue核心原理与前端工程化框架题出现了Vue的响应式原理虽然不是直接问你Vue2是defineProperty、Vue3是Proxy这么简单而是给了一段代码问修改某个属性后视图能否更新。这里考察的就是Object.defineProperty的局限——无法侦测对象新增属性和通过索引修改数组。Vue3用Proxy解决了这些问题能够拦截对象的所有操作。工程化方向有一道关于Webpack构建流程的题问loader和plugin的职责划分。核心理解loader是在模块加载时对模块源码进行转换是翻译官角色plugin是在构建流程特定的生命周期节点执行扩展操作比如打包优化、资源管理、环境变量注入等。这个理解了以后对Webpack的使用和调试会有很大帮助。还有一道题涉及babel的作用考察的其实是转译和polyfill的区别。Babel负责把ES6语法转换为ES5语法比如箭头函数转普通函数而core-js这类polyfill负责让旧浏览器支持新的API比如Promise、Array.includes。很多人把这两个概念混为一谈笔试里设置这种题目就是为了筛掉背概念但不理解本质的候选人。3. 算法题解题思路分享3.1 第一道算法题数组去重与排序变体这道题的描述是给定一个包含重复元素的数组返回每个元素在数组中首次出现的位置并按首次出现顺序输出。其实质是稳定去重。题目的难点不在于去重本身而在于要求保持首次出现顺序这就要求不能用纯Set快速去重而是用Map记录已出现的元素。我当时写的解法是这样的function uniqueWithFirstIndex(arr) { const map new Map(); const result []; arr.forEach((item, index) { if (!map.has(item)) { map.set(item, index); result.push(item); } }); return result; }如果光是用Set虽然能去重但遇到类似[3, 1, 3, 2, 1]这样的用例时Set可以保证顺序按插入顺序但其实如果去重标准变成了取首次出现的索引并排序问题就复杂化了。我遇到的是“由原数组操作变体返回去重后的新数组并保持每个元素在原始数组中最后出现的位置顺序”这个时候反着遍历会更方便function uniqueByLastIndex(arr) { const map new Map(); for (let i arr.length - 1; i 0; i--) { map.set(arr[i], i); } return Array.from(map.keys()).reverse(); }这里倒序遍历的思路在于Map.prototype.set会覆盖已有键值所以倒着遍历后每个键对应的位置是最后一次出现的位置但键的插入顺序是最后一次出现的顺序取反后正好是首次出现方向排序所需要的结果。这类题的考察重点是数据结构的选择和遍历方向的设计掌握了这个思路类似的变形题都能快速解出来。3.2 第二道算法题版本号比较版本号比较是前端笔试的高频题本质上考察的是字符串处理和边界条件处理能力。题目要求实现一个函数比较形如1.0.0和1.0.1的版本号大小可能包含多个点分段的数字且可能有前导零。我的实现思路是先按点拆分成数字数组然后逐个比较function compareVersion(version1, version2) { const v1 version1.split(.).map(Number); const v2 version2.split(.).map(Number); const maxLen Math.max(v1.length, v2.length); for (let i 0; i maxLen; i) { const num1 v1[i] || 0; const num2 v2[i] || 0; if (num1 num2) return 1; if (num1 num2) return -1; } return 0; }需要注意的点有两个一是1.0和1.0.0应该视为相同版本所以长度不一致时短的补0二是前导零的处理01和1要视为相等用Number转换后再比较就天然解决了。笔试中还有一个常见变体版本号里可能包含字母前缀比如1.0.0-beta和1.0.0-alpha。这种一般需要额外处理预发布版本的优先级规则。不过腾讯音乐这次考的版本号是纯数字格式没这个复杂度但备考时建议把这个变体也想清楚。3.3 笔试中算法题的战略取舍两道算法题都不算难但考察的是代码的规范性和边界处理能力。腾讯音乐笔试的算法题整体难度在LeetCode简单到中等之间没有出现动态规划和复杂图论。但这并不意味着算法题不重要——算法题在笔试中区分度很高一个错误的状态管理和溢出处理就能让一道题长时间卡住进而挤占后面问答题的时间。我的建议是平时刷题时要刻意练习三种能力快速分析边界条件的能力、写出规范变量名的习惯、现场用笔和纸走通思路的能力。笔试环境通常只有纯文本编辑器没有IDE的自动补全所以写代码的准确性和手速同样重要。4. 问答题与开放性问题应对策略4.1 首屏性能优化方案设计问答题的第一道是如果线上页面首屏加载过慢你会如何定位和优化这类问题属于典型的前端性能优化题考察的是系统性思维和实际项目经验。我当时列了一个从定位到执行的完整方案框架。定位阶段通过Chrome DevTools的Performance面板记录页面加载过程确认瓶颈在哪个阶段——是网络传输时间长、JavaScript执行阻塞、还是渲染过程太慢。再通过Network面板筛出耗时最长的资源看是单个大文件还是请求数过多导致的慢。优化层面我分了三类资源体积优化——用Webpack的代码分割配合懒加载把首屏不需要的模块延迟加载请求数量优化——域名合并、HTTP缓存合理配置、使用preload/prefetch提前加载关键资源渲染效率优化——减少DOM层级、避免长列表一次性渲染、关键CSS内联。还有一套字节的优化思路是这么说的首屏优化前先量化用Lighthouse跑分看FCPFirst Contentful Paint和LCPLargest Contentful Paint指标。一般FCP控制在1秒以内LCP控制在2.5秒以内超过这个范围就需要重点优化。如果没有性能实验平台的可以自己写脚本注入页面统计资源加载耗时。4.2 前端项目的工程化思考第二道问答题是开放式的在团队项目中你会如何推动前端工程的规范化和自动化这道题没有标准答案考察的是你对团队协作中痛点的理解和解决方案的落地能力。我当时的思路是从三个环节回答开发阶段引入ESLintPrettier并接入husky的pre-commit钩子从源头保证代码风格统一代码评审阶段制定一份Checklist关注但不限于状态管理是否合理、组件拆分是否得当、是否有明显影响性能的写法发布阶段用CI流水线跑单元测试和构建检查确保合入主干的代码是绿色的。这套方案不一定多高级但能够体现你在真实项目中推动过规范落地而不是空谈理想状态。整体来说开放性问答题的重点不在参考答案而在你有没有从实际场景出发的思考。比面试官是否认同方案更重要的是你能否清晰说出为什么这么做、解决了什么问题。4.3 用STAR原则组织问答题答案在回答开放式问题时推荐用STAR原则组织逻辑情境Situation、任务Task、行动Action、结果Result。笔试问答题没有与面试官交互的机会所以答案本身就要完整呈现这些环节。先说项目背景再说你的具体职责接下来是做了什么最后是效果如何最好有量化数据支撑比如体感流畅度提升、加载耗时减少到多少秒。这个方式的优点是既避免答得空洞又把你的真实项目经验自然融入进去。我有朋友问答题喜欢长篇大论写方案但缺乏具体场景和数据支撑得分并不理想。开放题想要拿高分关键还是在一个实字上。5. 备考建议与经验小结5.1 知识体系梳理优先级结合这次笔试的考题分布我给准备大厂前端笔试的同学一个知识优先级参考第一梯队必考且高频JavaScript作用域与闭包、事件循环与异步微任务、原型链与继承、this指向规则、HTTP缓存、浏览器渲染机制。这一块建议达到能给别人讲清楚的程度光能做对选择题不够遇到问答题变体很容易暴露概念理解的薄弱点。第二梯队出现概率较高CSS布局flex/grid、BFC、事件委托与冒泡捕获、跨域方案、Vue/React核心原理响应式、虚拟DOM、前端性能优化。第三梯队看批次运气Webpack构建原理、TypeScript类型体操、浏览器安全XSS/CSRF、设计模式、数据结构基础算法。系统准备时建议按照这个优先级分配精力把第一梯队的内容吃透性价比最高。5.2 真实笔试环境下的时间管理笔试和平时刷题完全不一样。笔试时的时间压迫感非常强遇到不会的题容易慌一旦慌乱好几道会做的题也会失分。我这次笔试采取的策略是单选题每道最多90秒拿不准的先标记不要原地纠结多选题可以多花点时间因为多选少选都不得分算法题先写思路注释再实现保证核心逻辑正确问答题列一个简短的提纲后再动笔避免越写越乱。有一点值得特别注意笔试平台的代码编辑器没有任何插件没有自动保存所以算法题的代码一定要自己控制好缩进和变量命名宁可多写注释也不要过度追求技巧。笔试成绩的评判中代码可读性也是加分项。5.3 当前前端笔试的新趋势与应对思路从这次笔试可以看出几个值得留意的趋势一是基础知识的考察越来越细甚至到了某个API参数级别的细节二是开放题的比例在增加更看重工程化和项目经验三是对代码风格和规范意识有了隐形考察。针对这些趋势我的建议是备考时不要只刷面试题集而要去系统地读一遍权威文档——MDN上JavaScript相关的核心概念、Vue和React的官方文档中关于原理和最佳实践的章节以及HTTP协议规范中缓存相关的段落。跟着文档走一遍比背十篇面经都管用。从我自己的经验来说现在的前端笔试真的不是背得越多分越高。面试官越来越在意候选人是否理解技术背后的原理以及是否具备解决实际问题的能力。这一点可能比考上什么题更重要。
返回列表