资讯动态

2023腾讯音乐春招前端笔试复盘:题型考点与避坑指南

发布时间:2026/9/1 4:09:52 来源:尧图企业网站定制
那阵子牛客网和力扣社区里全是“腾讯音乐春招笔试”的帖子。2023年这批前端卷子整体难度不算变态但覆盖范围确实广从基础语法到工程化、再到算法都有涉及。很多同学出来吐槽“选择题靠蒙手写题写一半算法题没时间”。我结合身边参加笔试的同学反馈和社区里的复盘帖把这套卷子从头到尾拆一遍帮后面准备同类岗位笔试的朋友少走点弯路。这套题主要分三块选择题/多选题、手写代码题、两道算法题。选择题部分考的是 JS 基础、浏览器和网络还有少量 Vue 和工程化手写题考的是数组去重、防抖节流这类常见场景算法题里有一道是“字符串最长无重复子串”LeetCode 3另一道是“数组扁平化 去重 排序”其实就是综合题。表面看不难但坑都藏在细节里。1. 整体题型分布与考点逻辑1.1 笔试题型与分值结构先说整体结构。2023年腾讯音乐春招前端笔试是牛客网系统时长一般是 90 分钟题量大约在 25 题左右。根据身边同学的反馈大致是这么分布的选择题单选多选15~18 题每题 2~3 分手写题1~2 题每题 10~15 分算法编程题2 题每题 20~30 分这里的核心矛盾是时间根本不够。90 分钟里选择题平均每题只有 3 分钟算法题要留出至少 35~40 分钟。很多同学在前面的选择题上花太多时间纠结最后算法题直接放弃。血泪教训是选择题遇到没把握的先标一下快速跳过别恋战。分值结构上算法题其实占了半壁江山。这也反映了大厂前端岗笔试的一个趋势不是考你背了多少 API而是考“能不能把想法用代码干净利落地表达出来”。这一点在后面第三部分我会展开讲。1.2 考点对应能力模型从这十几道题里能反推出面试官想考察的能力模型大致有三个维度。第一是基础功底是否扎实。JS 原型链、闭包、事件循环、类型转换这些是前端吃饭的本事选择题里反复出现。第二是工程化实践是否有概念。Vue 响应式原理、Webpack 打包流程、HTTP 缓存策略这些不是“会用”就够的笔试考的是“为什么”。第三是编码能力和边界意识。手写题和算法题考察的不只是能跑通还要考虑边界条件、时间空间复杂度甚至代码风格。我特意去翻了热搜词里的“前端开发规范vue”和“前端开发skills”这两条其实都指向同一个问题**现在笔试不满足于你会调库而是要看到你代码里的规范意识。**比如手写题的变量命名、注释习惯、边界处理都会被面试官一眼扫出来。很多人算法题写对了但命名是一坨 a、b、c这在面试评价里是很减分的。1.3 为什么前端笔试越来越偏“全栈化”还有一个值得琢磨的现象这套题里有不少考点实际上是后端和运维的内容比如 HTTP 状态码、浏览器缓存、CDN 原理。这不是腾讯音乐一家如此2023 年春招的整体风向都是这样。背后的原因是前端的边界在被不断打开。现在的业务开发不只是写页面还要考虑性能优化、接口设计、部署发布甚至参与 Node 中间层建设。所以笔试里出现大量网络和工程化题目本质上是在筛选“有全局视野”的候选人而不是只会写 CSS 和加事件绑定的同学。这也解释了为什么热词里出现“hzero前端开发”和“trea开发前端后端”这类搜索——因为大家已经意识到单靠 VUE 和 React 已经不足以支撑整个职业生涯了。前端要往上走必须理解前后端协作的全流程。这套笔试题里如果有一道 0 分的算法题还可以靠选择题补救但如果网络和工程化基础一塌糊涂那基本就被筛掉了。2. 核心知识点拆解与高频题目2.1 JS 基础选择题原型链、闭包与 this 指向选择题里最经典的一道是给定一个对象和方法判断 this 的指向。这种题在各大厂笔试里出现概率极高不仅是腾讯音乐字节、阿里也爱考。var name global; var obj { name: obj, say: function() { console.log(this.name); } }; var say obj.say; say(); // 输出什么答案是 global。原因很简单this 的指向是调用时决定的而不是定义时决定的。这里 say 被赋值给全局变量调用时上下文变成了全局所以 this.name 是全局的 name。这种题考察的就是对执行上下文的理解背是背不下来的得真正理解机制。另一道高频题是闭包和循环。经典的“var 的循环输出”只要考就一定有同学中招。for (var i 0; i 5; i) { setTimeout(() console.log(i), 1000); } // 输出什么输出是 5 个 5而不是 0、1、2、3、4。理解这个题的重点在于 setTimeout 是异步的等到回调执行时循环已经结束了i 已经变成 5。解决办法有三个IIFE 传参、let 声明、或者 bind。这道题考的就是闭包和异步的交叉地带。我的建议是准备这类题不要只背答案。你最好能把每一个选项为什么对、为什么错都讲清楚因为笔试里它可能给一个变体比如把 var 换成 let那答案就完全变了。2.2 网络与浏览器缓存、HTTP 状态码、跨域选择题里连续出现两三道 HTTP 相关的题这在前端笔试题里几乎是定番。2023 年这批考了这么几个方向浏览器缓存的优先级、301 和 302 的区别、还有跨域解决方案。浏览器缓存那题是典型的送分题但错误率很高。考的是强缓存与协商缓存的优先级关系**先查 Cache-Control再查 ETag/Last-Modified。**很多人记住了 Cache-Control 和 Expires但忘了还有一个优先级更高的 Pragma。虽然 Pragma 现在已经不怎么用了但老题里还是会拿它来挖坑笔试时看到 Pragma 不要慌它只是 HTTP/1.0 的遗留物优先级最高但也最快被废弃。跨域这块2023 年考了一道场景题前端要调用另一个域的接口后端已经开启了 CORS但浏览器还是报跨域错误。排查方向有几个请求是不是带了自定义 Header、是不是用了application/json的 Content-Type、有没有携带 Cookie涉及到配置Access-Control-Allow-Credentials: true。这道题对没有实际联调经验的同学来说比较吃亏因为选择题的选项往往都是“看起来都对”的。HTTP 状态码那题反而比较简单301 是永久重定向302 是临时重定向304 是协商缓存命中403 是禁止访问503 是服务不可用。至少 80% 的同学能答对但它的坑在于题干可能会问“哪些状态码下浏览器会默认做缓存”这个就涉及到 301、302、307、308 的区别了难度直接拉高。笔试里这种“从识记到理解”的递进式考法非常普遍。2.3 Vue 响应式原理与前端工程化热词里反复出现“前端开发规范vue”说明 Vue 依然是校招笔试的大头。这套选择题里考了 Vue 2 的 Object.defineProperty 和 Vue 3 的 Proxy 区别。这个知识点其实是一道“背诵 理解”结合的题。你需要知道以下几点Vue 2 用 Object.defineProperty 劫持对象的属性所以新增和删除属性无法被拦截需要借助Vue.set/Vue.deleteVue 3 用 Proxy 代理整个对象天然支持属性的新增与删除Object.defineProperty 需要递归遍历所有属性性能较差Proxy 的兼容性不如 defineProperty所以 Vue 3 不支持 IE笔试里容易出错的是把“无法监听新增属性”和“无法监听数组变化”搞混。Vue 2 对数组的限制是直接通过索引修改元素this.arr[0] xxx无法触发响应式更新必须用 splice 或 Vue.set。这在笔试题里经常以“以下哪个操作能触发更新”的选项出现。工程化方向考了一道 Webpack 的题hash、chunkhash、contenthash三者的区别。听起来简单但选项稍微绕一下就有人翻车。hash是整个项目构建的 hash项目里任何一个文件变了所有文件的 hash 都变chunkhash是每个 chunk 自己的 hash同 chunk 的文件共享contenthash是文件内容级别的 hash内容不变则 hash 不变实际项目中一般用contenthash做缓存策略配合 CDN 实现文件级别的精确缓存。笔试考这个不是为了让你背答案而是考察“你是否理解缓存和版本管理之间的关系”。这和前面 HTTP 缓存考题的思路是完全一致的——前端工程化和浏览器这层是打通的。2.4 ES6 进阶展开运算符与函数式写法热搜词里有“前端开发 函数 ...arg”这对应的就是展开运算符和 rest 参数的考点。这套笔试里虽然没有单独出大题但在手写题和选择题中都有渗透。一个典型的变体是实现一个函数接收任意数量的参数返回它们的和。用 ES6 的 rest 参数非常简洁const sum (...args) args.reduce((acc, cur) acc cur, 0);但如果出题人再往后问一步把数组里的字符串、数字混杂在一起要求把数字全部提取出来求和那么你不仅要会 rest 参数还要懂类型判断和 reduce 的灵活用法。这时候Array.isArray、typeof、Number.isFinite都是必须上场的。另一个和展开运算符相关的经典题是“合并两个对象并去重属性”。有人会直接写Object.assign({}, a, b)但这里要理解的是Object.assign的后面覆盖前面如果你是想保留某个对象的优先级要厘清顺序。const merged { ...a, ...b }; // b 的属性覆盖 a这套笔试题的出现顺序是先考选择题里的基础概念再在手写题里运用最后在算法题里做综合。如果你平时写代码就喜欢用展开运算符和 rest 参数这些题基本没有障碍。怕就怕只会写 for 循环看到这种写法觉得陌生那就吃亏了。一个缓解的小技巧是准备笔试前把 lodash 里常用的几个函数看一遍源码能大幅提升对函数式写法的熟悉度。3. 实操复盘手写题与算法题全解析3.1 手写题真题复盘数组去重与防抖节流2023 年腾讯音乐春招这批手写题主要有两道一个数组去重一个是防抖函数。看起来简单但满分率并不高。数组去重的常规写法至少有五种Set、filter indexOf、Map 记录、对象去重、双层 for 循环。大多数同学会写const uniqueArr (arr) [...new Set(arr)];这一行代码拿基础分没问题但如果题目要求“保留第一次出现的元素顺序”或者“对象数组按某个属性去重”那这道题就把很多人卡住了。对象数组去重的版本长这样const uniqueByKey (arr, key) { const map new Map(); return arr.filter(item { if (!map.has(item[key])) { map.set(item[key], true); return true; } return false; }); };这里能体现的加分点在于是否考虑到了 NaN 的去重问题。new Set是能用 NaN 去重的但如果是用indexOf就不行因为indexOf内部用的是严格相等而NaN ! NaN。这种细节就是你跟别人拉开差距的地方。防抖函数是另一道考察点。考得不是“能写出来”而是“要能处理参数和 this”。大部分人能写出function debounce(fn, delay) { let timer null; return function(...args) { clearTimeout(timer); timer setTimeout(() fn.apply(this, args), delay); }; }这里的关键是用apply绑定 this并把args透传。丢了 this 绑定的版本虽然能通过测试用例但在面试官眼里是不合格的。实际考场上还可能出现一个变体debounce要支持立即执行版本也就是第一次调用马上执行之后 delay 时间内再次调用不执行。能完整写出带immediate参数的防抖基本就拿到了这题的加分项。准备这一类题我建议你手写 注释把每一步的意思都写清楚这样面试官看回放牛客系统有回放功能的时候能感受到你是有意识地在写代码而不是硬背模板。3.2 算法题实战最长无重复子串先说说 LeetCode 3 的“最长无重复子串”这道题在 2023 年春招笔试里出现的频率极高。不仅是腾讯音乐美团、百度也有类似题目。题面很简单给定一个字符串s找出其中不含有重复字符的最长子串的长度。暴力法我就不展开了笔试时间紧张不建议写 O(n^3) 的解法。直接用滑动窗口O(n) 时间复杂度搞定const lengthOfLongestSubstring (s) { let left 0; let maxLen 0; const map new Map(); for (let right 0; right s.length; right) { if (map.has(s[right])) { left Math.max(left, map.get(s[right]) 1); } map.set(s[right], right); maxLen Math.max(maxLen, right - left 1); } return maxLen; };这个解法里最关键的一行是left Math.max(left, map.get(s[right]) 1)。很多人第一次写会直接left map.get(s[right]) 1这样在字符出现在左边界之前时会出现 left 回退的问题。比如字符串是abba当遍历到最后一个a时如果直接取map.get(a) 1left 会回到 1而正确的 left 应该是 3。用Math.max保证 left 永远不回退这是边界处理的关键。笔试时如果你把这个注释写在代码旁边比如写一句“left 不回退防止索引倒转”面试官会认为你真的理解了滑动窗口的精髓而不只是背了个模板。3.3 算法题实战数组扁平化 去重 排序这道题算是一个综合题题面大概是给定一个多维数组要求展平、去重、并升序排序。在 LeetCode 上没有完全一致的题但类似的组合题在很多公司笔试里都出现过。最简洁的写法是用flat(Infinity)加Set加sortconst processArray (arr) { return [...new Set(arr.flat(Infinity))].sort((a, b) a - b); };如果题目禁止使用flat就得手写递归或栈。递归版本const flatten (arr) { const result []; for (let item of arr) { if (Array.isArray(item)) { result.push(...flatten(item)); } else { result.push(item); } } return result; };这里要注意的地方是sort()默认按字典序排序也就是会把 10 排到 2 前面。笔试中 99% 的排序题都要传比较函数(a, b) a - b。这个细节每年坑掉大量考生因为本地自测的时候如果只测了 1~9 的数字根本发现不了问题。另外我建议这题主动用非递归栈的方式写一遍因为有些时候面试官会追问这段代码在数组嵌套很深的时候会不会爆栈递归写法确实在arr.flat(Infinity)和深层递归时可能遇到调用栈溢出问题虽然实际笔试很少考这么深但在系统设计面试时这是一个非常好的加分讨论点。如果一个候选人能主动提出“用栈代替递归避免栈溢出”面试官对这个候选人的评价会高很多。3.4 考场上如何分配时间基于这套题的结构我建议的答题策略是优先做手写题和算法题共约 40~50 分因为它们确定性最高写对就有分选择题控制在 40 分钟内会做的直接选不会的标记后跳过最后如果有时间再回来看标记的选择题很多人习惯按顺序做结果前面选择题里的一道多选卡了 10 分钟后面算法题只剩 10 分钟代码没写完白白丢了 30 分。95% 的人失败不是题不会做而是时间规划出了问题。我在实际笔试复盘时发现能在 90 分钟内把算法题完整提交的人通常会先花 2 分钟读题、5 分钟想思路、10 分钟编码、3 分钟自测。直接在编辑器里边写边想的10 个里有 7 个会在最后因为边界情况过不了用例。4. 常见致命失误与避坑实战指南4.1 误区一忽视环境差异本地跑通却提交失败这是最常见、也最让人沮丧的问题。本地用 Node 跑很顺畅复制到牛客系统就报错。原因千奇百怪有的考试环境是老版本浏览器不支持Array.prototype.flat有的对const和let的限制严格还有的是牛客的输入输出模板读不到数据。特别是Array.prototype.flat这个东西ES2019 才正式纳入标准。如果笔试环境是旧内核flat直接不存在。稳妥方案是在做题时少用太新的 API或者主代码里自己手写flat函数。笔试永远选最稳妥的写法用Array.isArray 递归代替不熟悉的库函数看起来傻但一定不出错。另一个常见问题是输入输出格式。牛客的 ACM 模式需要自己读输入很多刷 LeetCode 习惯了的同学完全不会处理比如输入是一行 JSON 字符串需要JSON.parse后再操作结果直接拿字符串当数组用半天找不出 bug。准备这类笔试一定要用牛客或者赛码网练几道“老题”刷一下输入输出手感不然真的会写不进去。4.2 误区二代码规范稀烂隐形扣分严重上面提到过牛客系统是支持回放和代码展示的面试官会看你写的代码。很多同学在笔试结束后觉得自己算法没问题结果综合评价不高这就是因为代码规范暴露了问题。最常见的规范问题包括变量命名是a、b、c没有空行和缩进函数没有注释一个函数里硬塞了几十行逻辑。你可以换个角度想如果你在 code review 时看到同事提交这么一份代码你愿意放他过吗本质上笔试题考察的就是“你以后在工作中提交代码的质量”。这里建议准备一套自己的代码模板包括常用的函数命名习惯、边界检查写法、注释风格。比如我习惯在写 LeetCode 题时做三件事函数定义写在最前面边界情况统一用 if 判断并直接 return关键算法行加一行中文注释。// 解法滑动窗口 // 思路右指针遍历左指针按需收缩 const lengthOfLongestSubstring (s) { if (!s.length) return 0; // 边界 // ... 核心逻辑 };这套套路不一定最高效但保证了在所有代码里看起来一致、专业。4.3 误区三算法题不手动测试边界我知道考场上很紧张打完代码就直接提交然后看到“测试用例通过 0%”。这种情况通常是因为没考虑空输入、单字符、全重复字符、全唯一字符这些边界条件。以“最长无重复子串”为例至少应该手动跑这几个用例s 期望输出 0s 期望输出 1s bbbbb期望输出 1s abcabcbb期望输出 3不要嫌麻烦在提交以前跑一遍这些用例大概能挡住 70% 的失误。还有一个更实用的小技巧刻意把数组或字符串长度设置为 1 再跑一遍因为很多逻辑在长度大于 1 时正常但在长度为 1 时会触发数组越界。这个习惯养成之后不只是笔试工作中的代码 bug 也能少很多。4.4 误区四知识面太窄忽略工程化和网络坦白说笔试中选择题的很多内容在业务开发中并不常用。比如 Webpack 的contenthash平时很少手动配HTTP 缓存有一套现成的默认逻辑也不用手工排查。但笔试它就是要考因为没有这些底层知识遇到线上问题就会束手无策。备考方案是前端面试的八股文必须背但要理解性记忆每个知识点至少追问两个“为什么”。比如 Cache-Control 的max-age和no-cache的区别不只是选项面试官会追问“如果页面更新了但用户看到的还是旧内容你会怎么排查”。能在笔试前把前端知识体系过一遍对后续面试帮助极大。还有一个信息不对称的问题很多人不知道现在笔试已经出现了 AI 辅助工具限制问题。部分系统会监控浏览器切屏你一边做牛客一边搜索很容易被判违纪。所以复习阶段必须把知识点吃透真正上考场不要想着查资料踏踏实实凭本事写。4.5 实用刷题规划考前 4 周怎么做如果距离笔试还有一个月我建议分三阶段推进第 1 周把 JS 基础和前端核心八股过一遍尤其是 this、闭包、原型链、事件循环、HTTP、缓存形成知识图谱第 2~3 周集中刷题LeetCode 高频题 100 道 牛客前端笔试题合集重点练滑动窗口、双指针、DFS/BFS、动态规划入门第 4 周做 3~5 套完整模拟题严格按 90 分钟计时练习时间分配刷题时不贪多每天 2~3 道精做尽量写出多种解法并比较时间复杂度和边界条件。一套题刷三遍比三套题刷一遍的效果好得多——这是十几场笔试下来最实在的经验。5. 笔试之外的加分项如何让“代码”替你说话5.1 简洁但不过度压缩有些同学为了显示自己很“聪明”会在笔试里写一些极简代码一行执行完所有逻辑。但这样通常有副作用变量不清晰、没有注释、跑出问题不好排查。笔试代码的调性应该是清晰优先其次再谈简洁。判断标准很简单如果你的代码能在 10 秒内被另一个工程师看懂那它就是合格的。如果你自己写完之后要盯着屏幕看 1 分钟才想起来逻辑是什么那后面面试官看回放时也同样看不懂这不是聪明而是制造麻烦。5.2 注释写“为什么”而不是“是什么”很多同学写注释喜欢写“定义了一个变量 count”这属于废话注释。高价值的注释写的是“为什么”比如// 这里使用 Math.max 防止 left 指针回退避免重复字符出现在左边界之前导致窗口重置 left Math.max(left, map.get(s[right]) 1);这种注释体现的是你的思考过程即使代码有地方写得不完美面试官看到这种注释也会觉得你的思路是清晰的。在实际手写题中我甚至建议在函数开头加一行“核心思路”注释哪怕题目已经说明得很清楚了这也能起到给自己理清思路的作用。5.3 考试结束前 5 分钟的检查清单最后 5 分钟不需要再写新功能了而是做检查有没有没用的调试代码console.log没有删掉变量名是否有明显拼写错误有没有没跑过的边界用例所有函数是否都指定了返回值有没有写错比较顺序比如sort((a, b) b - a)是降序但题目要求升序这个习惯是用多次失败换来的。曾经有同学考试结束前 3 分钟发现自己的快排比较符写反了直接改完过全量测试。这种临门一脚的检查往往能救回 10 分以上。6. 从春招笔试看未来前端岗的考试趋势虽然这是 2023 年的笔试复盘但里面的趋势在后两年依然有效而且会被强化。第一个趋势是考察范围越来越大从纯 JS 语法扩展到 HTTP、浏览器原理、Node、工程化甚至包括性能和监控。如果你只会写 React/Vue 业务组件笔试会很被动。第二个趋势是手写题的场景化不再是“实现一个 debounce”这么简单而是“搜索框输入时要求 300ms 内只发起最后一次请求写出实现”其实就是防抖的应用。场景化题目考察的其实是“你能否从业务描述里识别出技术模型”。第三个趋势是AI 工具的引入导致“人”的编码能力更被看重。试想一下能问 AI 答出标准解法的时代笔试的目的就不只是筛选“会不会”而是筛选“有没有能力独立解决问题”。代码风格、边界意识、代码整洁度这些在 AI 工具盛行的背景下反而成了区分度更高的点。这也解释了为什么现在主观题、设计题的权重在提升。对准备下一次笔试的朋友我的建议是不要局限于背题要把知识体系搭起来。前端八股图谱、算法模板、笔试环境练习、代码规范这四件事看上去老生常谈但每次能真正做透的人并不多。你不需要一夜之间成为算法大师但至少要成为一个“代码读得懂、写得清、跑得对”的人。把一件事做到这个程度比盲目刷 300 道题有用得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价