ARTICLE DETAIL

资讯详情

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

腾讯音乐前端笔试复盘:从基础考点到编程题全解析

腾讯音乐前端笔试复盘:从基础考点到编程题全解析 先聊个实在的腾讯音乐秋招前端岗的笔试到底在考什么我前后带过不少新人也帮人改过简历、做过模拟面试。2023年腾讯音乐秋招第二批前端开发岗的笔试题整体风格和往年一脉相承——不搞偏题怪题但非常考验基础功底和代码熟练度。如果你准备过一段时间八股文看到题会觉得很亲切但如果你只是背过概念、没怎么手写过代码这次笔试会给你一个比较直接的提醒前端这个岗位光会“说”是不够的必须能“写”。这篇文章我按自己的复盘思路把整张卷子拆开揉碎从题型分布、核心考点、手写代码题的解法和踩坑点、再到笔试之后的面试衔接一条线捋清楚。不管你是准备秋招、春招还是单纯想检验一下自己的前端基本功这篇内容都值得花二十分钟认真看一下。尤其是那些准备投递大厂中厂前端岗的朋友腾讯音乐的这套题基本可以当作前端笔试的“标尺”来对待。1. 腾讯音乐笔试的整体风格与题型分布先说结论腾讯音乐前端岗的笔试不是那种“故意刁难人”的卷子。它考察的核心就三件事——JavaScript语言功底、前端框架尤其是Vue的实际运用能力、以及你用代码解决真实问题的工程思维。1.1 题型构成与时间分配我记得很清楚整张卷子大概分四个部分单选题、多选题、填空题、编程题。单选和多选覆盖的知识面很广从ES6语法、浏览器缓存机制、HTTP状态码到Vue响应式原理、组件通信方式都有涉及。填空部分偶尔会出一些让你写输出结果的题比如this指向、闭包、事件循环输出顺序之类的。编程题通常是两道一道偏算法/逻辑一道偏业务/组件实现。整场笔试的时间一般是一个半小时到两个小时。我见过不少同学在选择题上纠结太久导致最后编程题没时间写或者写得非常仓促。这里先给个建议前面选择填空部分会的题快速过拿不准的题先凭第一印象选然后标记出来等编程题写完了再回来慢慢斟酌。千万不要在一道纠结题上耗掉十分钟得不偿失。1.2 和行业其他大厂笔试的横向对比如果横向对比一下腾讯音乐的笔试难度在互联网公司里属于中等偏上一点点。比字节、快手的部分岗位要温和比很多中小厂的卷子要扎实。它的特点是不考ACM竞赛那种高难度算法更偏实际开发中能用到的逻辑题比如数组处理、字符串解析、树结构转换这类。Vue相关的题目占比明显高于React这点和腾讯音乐的技术栈有直接关系比如QQ音乐、全民K歌等产品线大量使用Vue。后面聊到题型细节大家就能感受到这个倾向。注意腾讯音乐和腾讯集团虽然有关系但校招是独立进行的笔试系统、投递渠道、招聘流程都单独走。准备时别混淆了尤其不要拿腾讯集团笔试的题量和难度来直接对标腾讯音乐。2. 选择与填空高频考点拆解选择题和填空题占的分值并不低而且往往是拉开差距的地方。编程题大家都会写一些但基础题的正确率才是真正决定你能不能进面试的关键。我把自己印象里比较常考的几类知识点整理了一下这些都是我在辅导新人时反复强调的重点。2.1 JavaScript语言基础闭包、this、事件循环JavaScript基础这一块闭包几乎是必考的。常见考法是给你一段代码问输出结果或者问闭包可能带来的内存泄漏问题。举个例子经典的for循环中用var声明和用let声明的区别for (var i 0; i 5; i) { setTimeout(() { console.log(i); // 输出 5 5 5 5 5 }, 0); } for (let i 0; i 5; i) { setTimeout(() { console.log(i); // 输出 0 1 2 3 4 }, 0); }var没有块级作用域循环结束后i已经变成5所以定时器回调读到的都是5。let有块级作用域每一轮循环的i都是独立的绑定所以能正确输出0到4。如果笔试里出了这个题不要只答对结果最好能解释清楚背后的作用域机制这对后面的问答题可能有帮助。事件循环也是高频中的高频。尤其是宏任务和微任务的执行顺序我建议你把下面这个经典案例吃透console.log(script start); setTimeout(function() { console.log(setTimeout); }, 0); Promise.resolve() .then(function() { console.log(promise1); }) .then(function() { console.log(promise2); }); console.log(script end);输出顺序是script start - script end - promise1 - promise2 - setTimeout。原理就是同步代码先执行微任务队列在处理宏任务之前会被清空Promise的then回调属于微任务setTimeout属于宏任务。这个点不仅笔试会考面试时也经常拿出来聊。2.2 浏览器原理与网络基础浏览器缓存策略绝对是选择题里的常驻嘉宾。强缓存和协商缓存的区别、Cache-Control和Expires的区别、ETag和Last-Modified的区别这些都要弄得清清楚楚。简单梳理一下强缓存浏览器直接从本地缓存读取资源不发请求到服务器。相关字段是Cache-Control比如max-age3600和Expires。协商缓存浏览器带着缓存标识向服务器发起请求由服务器判断缓存是否可用。相关字段是ETag/If-None-Match和Last-Modified/If-Modified-Since。这里有个容易被忽略的小细节如果同时存在Cache-Control和Expires以Cache-Control为准。因为HTTP/1.1的Cache-Control优先级高于HTTP/1.0的Expires。HTTP状态码也是选择题重灾区。我印象里腾讯音乐考过301和302的区别、403和404的区别、500和502的区别。这里总结一下状态码含义典型场景301永久重定向网站域名变更旧地址永久跳转到新地址302临时重定向登录后跳转、活动页面跳转304未修改协商缓存命中服务器告诉浏览器用本地缓存403服务器拒绝请求没有权限访问资源404资源不存在访问了不存在的URL500服务器内部错误后端代码抛异常502网关错误反向代理服务器收到无效响应2.3 Vue核心原理与常见API考察Vue在腾讯音乐的笔试中占比很大从选项题的分布来看Vue2和Vue3都会涉及但Vue3的比重在逐年增加。尤其是2023年的这批题composition API相关的考点已经非常多了。响应式原理是必考的。Vue2用Object.definePropertyVue3用Proxy。这里常考的坑是Vue2无法检测对象属性的新增和删除需要用Vue.set或Vue.delete数组的index直接赋值也无法触发更新要用splice。Vue3的Proxy则解决了这些问题可以拦截更多操作。组件通信方式也是高频考点。父子组件用props和$emit父传子用props子传父用$emit自定义事件跨层级的可以用provide/inject任意组件通信用事件总线Vue2的EventBus或者Vuex/Pinia。有一年笔试还出了道多选题问“以下哪些可以用于Vue组件通信”选项里混着$refs、$children、$parent这些其实都能用就是适用场景不同。computed和watch的区别也值得好好整理一下。computed是基于依赖的响应式缓存只有在依赖变化时才会重新计算watch是监听某个值的变化然后执行回调函数。笔试里可能给一个具体的业务场景问应该用computed还是watch。比如“根据firstName和lastName拼接fullName”用computed更合适比如“监听路由变化然后发起请求”用watch更合适。2.4 高频手写题不只是背答案腾讯音乐笔试题里有一类“伪手写题”——就是填空形式给你一段不完整的代码让你补全某一行。这种比直接让你从零写要简单但前提是你真的理解代码的逻辑而不是背答案。比如我印象里考过这样一道题给你一个防抖函数中间挖掉一行让你补function debounce(fn, delay) { let timer null; return function(...args) { // 请补全这里 const context this; clearTimeout(timer); timer setTimeout(() { fn.apply(context, args); }, delay); }; }补全的内容就是clearTimeout(timer)但如果你不理解防抖的逻辑你可能不知道怎么填。这种题其实比让你独立写一个防抖更考验理解深度因为你要根据上下文猜出缺的是什么。不过我还是建议你把防抖、节流、深拷贝、数组去重、发布订阅、Promise.all这类经典手写题全部背熟、写熟。因为在笔试的编程题环节这些工具的变体出现概率极高。下面我详细说说编程题。3. 编程题实战思路与完整实现编程题是整个笔试的压轴一般两道题分布在两个不同的难度段位。第一题通常比较温和考察基本的编码能力第二题会稍微复杂涉及一些业务逻辑或数据处理。我把腾讯音乐常考的几类编程题整理了一下每道题都给出完整思路和解题代码。3.1 大数相加笔试经典题必须拿分大数相加是一道非常有代表性的题。JS的Number类型有安全整数范围超过Number.MAX_SAFE_INTEGER9007199254740991的整数运算就会丢失精度。实现大数相加的思路是把数字转成字符串然后按位相加处理进位。function addBigNumbers(num1, num2) { let i num1.length - 1; let j num2.length - 1; let carry 0; let result ; while (i 0 || j 0 || carry 0) { const digit1 i 0 ? parseInt(num1[i]) : 0; const digit2 j 0 ? parseInt(num2[j]) : 0; const sum digit1 digit2 carry; result (sum % 10) result; carry Math.floor(sum / 10); i--; j--; } return result; } console.log(addBigNumbers(9007199254740991, 9007199254740991)); // 输出18014398509481982重点有两个一是从低位往高位算所以要倒序遍历字符串二是进位处理sum大于等于10时要向下一位进1。这道题我至少在三家公司的笔试题里见过属于必会的基础题。3.2 树结构转换从业务场景中抽象出来的难题有一年腾讯音乐的编程题考了“将扁平数组转换成树形结构”的题目。这道题很经典因为它直接对应前端实际开发中的场景——比如把后端返回的菜单列表、组织架构数据渲染成树形组件。题目大概长这样给定一个扁平数组每个元素有id、parentId、name等字段要求转换成树形结构。const input [ { id: 1, parentId: 0, name: 首页 }, { id: 2, parentId: 0, name: 关于我们 }, { id: 3, parentId: 1, name: 产品中心 }, { id: 4, parentId: 3, name: 产品A }, { id: 5, parentId: 3, name: 产品B }, ]; function buildTree(arr) { const map new Map(); const roots []; // 第一轮遍历把所有节点存入Map arr.forEach(item { map.set(item.id, { ...item, children: [] }); }); // 第二轮遍历把节点挂到对应的父节点下 arr.forEach(item { const node map.get(item.id); if (item.parentId 0) { roots.push(node); } else { const parent map.get(item.parentId); if (parent) { parent.children.push(node); } } }); return roots; } console.log(JSON.stringify(buildTree(input), null, 2));这里推荐用Map来实现因为Map查找是O(1)复杂度整体时间效率为O(n)。如果你用数组的find方法去找父节点那复杂度就变成O(n²)了数据量一大性能就会有问题。这个思路差异在笔试里不一定能体现出来但在面试时如果被追问复杂度分析能答上来会很加分。3.3 版本号排序字符串处理与比较逻辑的经典题这道题也很有代表性。给一组版本号例如[1.0.2, 1.0.1, 2.0.0, 1.1.0, 2.1.0]要求按版本号从小到大或从大到小排序。版本号的比较规则是从左到右逐段比较数字大小。直接的sort方法不行因为版本号是字符串默认按字典序排序会出现1.10.0排在1.2.0前面的问题——字典序比较时10小于2但版本号规则里10大于2。解题思路是把版本号按.分割成数组然后把每一段转成数字再比较。function compareVersions(v1, v2) { const parts1 v1.split(.).map(Number); const parts2 v2.split(.).map(Number); const len Math.max(parts1.length, parts2.length); for (let i 0; i len; i) { const num1 parts1[i] || 0; const num2 parts2[i] || 0; if (num1 num2) return 1; if (num1 num2) return -1; } return 0; } const versions [1.0.2, 1.0.1, 2.0.0, 1.1.0, 2.1.0]; const sortedVersions versions.sort(compareVersions); console.log(sortedVersions); // 输出[1.0.1, 1.0.2, 1.1.0, 2.0.0, 2.1.0]这里有个关键细节parts1[i] || 0。当两个版本号的段数不一致时比如1.1和1.1.0缺省的那一段按照0处理。这个逻辑很重要很多人写的时候容易忽略。3.4 虚拟滚动实现考察框架业务能力的高级题有一年笔试的编程题出了一道让人印象深刻的业务题实现一个虚拟滚动列表渲染长列表时只渲染可视区域内的数据。虽然题面给的是React或Vue任选但我印象里绝大多数人会选Vue毕竟腾讯音乐本身是Vue技术栈。虚拟滚动的核心思想是只渲染可视区域的列表项而不是渲染全部数据。具体做法是外层容器固定高度并滚动内层用一块高度等于全部数据总高度的“垫片”来撑起滚动条然后根据scrollTop计算可视范围的起始索引和结束索引只渲染这个范围内的项。这里我给出一个Vue3的实现思路template div classvirtual-scroll scrollhandleScroll div classvirtual-scroll__phantom :style{ height: totalHeight px }/div div classvirtual-scroll__content :style{ transform: translateY(${startOffset}px) } div classvirtual-scroll__item v-foritem in visibleList :keyitem.id :style{ height: itemHeight px } {{ item.text }} /div /div /div /template script setup import { ref, computed } from vue; const props defineProps({ list: { type: Array, required: true }, itemHeight: { type: Number, default: 50 }, containerHeight: { type: Number, default: 400 } }); const scrollTop ref(0); const totalHeight computed(() props.list.length * props.itemHeight); const visibleCount computed(() Math.ceil(props.containerHeight / props.itemHeight)); const startIndex computed(() Math.floor(scrollTop.value / props.itemHeight)); const endIndex computed(() startIndex.value visibleCount.value); const startOffset computed(() startIndex.value * props.itemHeight); const visibleList computed(() props.list.slice(startIndex.value, endIndex.value)); function handleScroll(e) { scrollTop.value e.target.scrollTop; } /script style scoped .virtual-scroll { position: relative; height: 400px; overflow-y: auto; background: #fff; } .virtual-scroll__phantom { position: absolute; top: 0; right: 0; left: 0; } .virtual-scroll__content { position: absolute; top: 0; right: 0; left: 0; } .virtual-scroll__item { display: flex; align-items: center; border-bottom: 1px solid #eee; } /style这个实现的核心知识点有三个总高度用假想高度撑开滚动条、内容区通过translateY位移实现“视口跟随”、可视数据通过slice裁剪。只要把这三个点讲清楚面试官通常会认可你的理解深度。我见过很多人能写出虚拟滚动的大致结构但一追问“为什么用translateY而不是top”就卡住了。这里顺便说一句用transform不会触发浏览器的重排reflow性能更好用top会触发布局计算滚动时会卡顿。4. 实战避坑我在复盘腾讯音乐笔试时总结的教训这些内容是我接触大量真实笔试复盘案例后总结出来最有共性、也最容易被忽略的“坑”。如果你正在准备校招下面每一条都值得认真对待。4.1 选择题的“陷阱”设计思路很多同学以为自己挂在了编程题上其实真正的失分大户是选择题。腾讯音乐的选项设计很讲究它不会把错误的选项写得很离谱而是故意写得“看起来有道理”。举几个常见的陷阱类型把Object.defineProperty和Proxy的差异混淆选项里故意把Vue3的Proxy写成“无法监听嵌套对象变化”其实Proxy仍然需要递归代理才能实现深层响应式但它监听的是对象整体而不是属性。把强缓存和协商缓存的触发时机搞混选项里故意说“Cache-Control是服务器返回响应时设置的首部优先级低于Expires”这个说法就是错误的因为实际是Cache-Control优先级更高。把HTTP 301和302的场景互换选项里说“301是临时重定向302是永久重定向”正好反了。所以做选择题时如果一个选项看起来很合理不太对劲的先想想它是不是反着说的。腾讯音乐出题很喜欢用“颠倒法”来测试你对概念的真实掌握程度。4.2 编程题最容易丢分的三件事第一审题不清。很多人都栽在这里。比如题目要求返回一个数组你却返回了字符串题目要求改变原数组你却生成了新数组。建议拿到题先花30秒看清楚输入是什么、输出是什么、有没有要求原地修改、有没有要考虑边界条件。第二边界处理不全。比如大数相加的输入可能包含空字符串版本号排序的输入可能有空数组树结构转换的数组可能没有根节点parentId等于0的节点。如果你没有做防御性校验代码一跑就崩用例直接挂零。第三忘记复杂度分析。笔试系统一般不会单独考复杂度但如果你在面试中被问到自己写的算法复杂度是多少、能不能优化回答不出来是很减分的。平时练题时要有意识地分析自己代码的时间复杂度和空间复杂度。4.3 时间分配策略为什么重要我复盘过不少同学的笔试记录发现一个规律能进面试的人基本都会留出至少30到40分钟写编程题。如果你前面选择题花了太多时间编程题只能草草收尾那笔试成绩基本无望。建议的分配策略是前10分钟快速扫描全卷标注出选择题里的难题和不确定题。中间20到30分钟先写编程题因为编程题分值高、得分确定性也高。剩余时间回头处理选择题里的难题确保在提交前没有空白题。这个策略的核心逻辑是选择题再怎么纠结正确率也不会从30%提升到90%但编程题只要写出来拿到的分数是实打实的。把时间花在回报更高的题目上是最理性的选择。4.4 笔试后的复盘思路比分数更重要很多同学笔试结束后就彻底放松了等结果出来才慌。我的建议是笔试结束的24小时内立刻复盘。把编程题重新在自己电脑上实现一遍把选择题里不确定的题目查清楚整理成错题集。因为这时候记忆最清晰复盘效果最好。更重要的是笔试里出现过的知识点经常会在面试里被追问。比如你笔试遇到了虚拟滚动面试时面试官可能会问“虚拟滚动时如果列表项的高度不固定怎么办”“如果滚动容器里还有其他的内容怎么处理”这些问题如果你在笔试后的复盘里想过面试时就能从容应对。5. 从笔试题反推大厂前端团队的人才标准聊完具体的题目我更想聊一个从这套笔试题里折射出来的东西——腾讯音乐这样的团队到底在筛选什么样的人。5.1 扎实的计算机基础仍然不可替代从选择题的分布可以看出来浏览器缓存、HTTP状态码、事件循环、作用域链这些计算机基础和网络基础知识依然占据很大的比重。有些同学总觉得这些“太底层”“过时了”喜欢去追新的框架和工具。但笔试的题量分布说明团队在筛选候选人时首先看重的是基础是否扎实。这背后是有道理的基础扎实的人学习新框架的成本低排查问题的能力强。框架更新换代很快今天学Vue2明天Vue3后天又有新工具但JavaScript语言的核心机制、浏览器的渲染原理、网络协议的基本逻辑是稳定的。团队需要的是能长期成长的人而不是只会某一种框架的“工具人”。5.2 业务理解与代码实现同等重要编程题里出现树结构转换、虚拟滚动这类题目说明团队不是在招“刷题机器”而是在招能解决真实业务问题的工程师。树结构转换对应权限菜单、组织架构等业务场景虚拟滚动对应长列表性能优化这些业务场景在QQ音乐、全民K歌、酷我音乐等产品中都是真实存在的。所以如果你能在笔试中写出代码并且通过注释或在面试时说明“这段代码用在什么业务场景”“解决了什么性能问题”会比单纯写出正确答案更打动人。因为笔试系统只能看到你的代码但面试时你能展示出自己的业务思考这是加分项。5.3 代码风格体现工程素养还有一个小细节笔试的时候尽量保持代码风格干净规范。变量命名用有意义的英文名而不是a、b、c函数内部逻辑用空行分隔关键步骤加注释。虽然笔试系统不会因为命名不规范扣分但你的代码会被面试官看到。在面试前面试官通常会调阅你的笔试代码。整洁的代码风格和混乱的代码风格给面试官留下的第一印象是完全不同的。我记得有个真实的例子有个同学笔试编程题完全做对了但代码命名全是xxx1、xxx2、xxx3中间夹杂着大量调试用的console.log。面试官看到之后第一句话就是“你这代码风格不太行啊”。就因为这种小事最后offer就没发。这不是危言耸听代码风格在面试里的重要性比很多人想象的要高得多。6. 给你的最后建议我聊了这么多最后再分享几个比较实际的建议。这些建议不是我凭空想出来的是我在辅导那么多人准备校招笔试之后发现的最有效的提升路径。第一把基础打牢永远是第一优先级。不要觉得ES6语法、事件循环、闭包这些太简单就不屑于复习恰恰是这些“简单”的东西决定了你的下限。我的建议是每天花一个小时过一遍JavaScript基础尤其是手写Promise、手写防抖节流、手写深拷贝这三件套必须练到闭着眼都能写出来的程度。第二Vue一定要动手写项目而不是只看视频。腾讯音乐笔试里的Vue相关题目如果你的Vue是“看的”而不是“写的”很容易在细节上翻车。自己搭一个简单的后台管理系统把组件通信、路由守卫、状态管理、自定义指令这些全过一遍比看十遍教程都管用。第三笔试前一定要上牛客网、力扣把这些经典题刷透。大数相加、数组转树、版本号排序、虚拟滚动这些题目在牛客网和力扣上都有原题变体。刷题的时候不要只看思路一定要自己在编辑器里敲一遍跑通为止。只看不写的人上了考场一定会发现手生。第四笔试结束后立刻复盘把错题整理成文档。这个习惯会让你在面试环节受益无穷。我见过太多人笔试过了但面试时被问到笔试的编程题支支吾吾说不清楚当时的思路显得像网上抄的答案。如果你能在笔试题基础上说出“如果让我重新写我会在某个地方做优化”面试官会立刻对你好感大增。从笔试到面试从面试到offer看起来每一步都很难但其实每一步都有迹可循。技术岗位的招聘本质上是在筛选“基础扎实、能干活、有潜力”的人。只要你有方向、肯下功夫、愿意不厌其烦地打磨自己的代码能力拿到心仪的offer只是时间问题。我想说的就这些希望对正在准备秋招的你有所帮助。
返回列表