ARTICLE DETAIL

资讯详情

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

腾讯音乐前端笔试复盘:JS异步编程与框架考点全解析

腾讯音乐前端笔试复盘:JS异步编程与框架考点全解析 前阵子帮朋友复盘腾讯音乐2023年春招前端岗第二批笔试发现这套题挺有嚼头。和很多大厂笔试不同它没有一上来就甩几道hard级算法题吓唬人而是把考察重心放在了JS语言功底、异步编程理解、框架实战细节和一部分工程化素养上。题目整体风格是“看着都眼熟做起来全是坑”非常考验基础是否扎实。这篇文章我把整套笔试的题型分布、考察逻辑和重点题目拆开揉碎了讲再附上我自己做下来的思路和复盘心得。无论你是准备投腾讯音乐还是想摸底一下当前大厂前端笔试的普遍水平这篇都能给你一个比较清晰的参照系。1. 题型分布与整体难度先给这套试卷画个像1.1 题型构成与分值分布腾讯音乐春招笔试用的是牛客网的系统第二批和第一批的题目不完全一样但整体结构基本保持稳定。整套试卷由两部分组成单选题和多选题混合的选择题部分加上三道编程题。从体感上看选择题大概20道左右每题分值不高编程题三道分值权重明显更高是拉分的关键。整个考试时间大概120分钟时间分配压力不小。我整理了一下这批笔试的考点分布大致可以分成这样几块考察模块大致占比具体考点举例JavaScript基础30%类型转换、闭包、作用域、this指向、原型链异步编程20%Promise、事件循环、async/await输出顺序框架与工程化25%Vue响应式原理、组件通信、代码规范浏览器与网络10%缓存策略、渲染流程、跨域编程题15%数组/字符串处理、手写API、算法实际做下来选择题里JS基础的比重比预想中还要高尤其是异步输出顺序的题几乎每次笔试都会遇到几道变体。框架部分则偏向Vue和React都会涉及但Vue的题目在腾讯音乐这套卷子里略多一些。1.2 从难度曲线看这批笔试的筛选逻辑这套卷子的难度曲线设计得挺有意思。前面十道左右的选择题属于基础热身只要你平时写代码不是完全依赖框架、对JS本身有基本理解基本能答对。到了中间段落难度开始爬坡会出现一些需要细想的类型转换题、闭包陷阱题这时候就筛掉了一批似懂非懂的选手。编程题部分更是典型的“看着简单做着难”。第一道题往往比较友好让你建立信心第二道就开始考真正的逻辑能力第三道则有一定区分度需要你能写出时间复杂度和空间复杂度都可接受的解法。这套筛选逻辑背后体现的是腾讯音乐对前端工程师的定位他们不指望你是个算法竞赛选手但要求你有扎实的语言功底能写出靠谱的业务代码同时对框架底层有一定理解。换句话说他们筛的是什么筛的是那些“用过API但不理解原理”的人。这对我后来准备其他大厂笔试也有启发刷题固然重要但比刷题更重要的是把每一个基础概念真正想透。2. 选择题里的高频考点JS基础与异步编程是主战场2.1 类型转换与表达式求值选择题里的“送命题”这批笔试的选择题里类型转换相关的题出现频率极高而且几乎每一道都有迷惑性。看着是送分题实际上暗藏杀机。我印象比较深的一道题大概是这样的console.log([] ![]); console.log([] 0); console.log([1, 2] 1,2);这道题考察的是对象转原始值、布尔值转换、以及宽松相等的比较规则。很多人第一反应是[] ![]结果为false因为觉得空数组和数组取反肯定不相等。但实际上![]先被求值为false因为数组对象是truthy而[] false时两边都会转成数字进行比较[]转数字是0false转数字也是0所以结果是true。这类题说白了就是考你有没有真正理解隐式转换的规则对象转原始值会先调用valueOf()如果没有返回原始值再调用toString()比较时如果一边是对象一边是数字/字符串对象会转原始值再比较布尔值参与比较时会先转成数字我当时做这类题的策略是不在心里硬算而是先把转换链写在草稿纸上一步一步来。比如[] ![]先拆成[] false再拆成0 0答案就出来了。这种题只要你别急躁基本不会错。还有一个变体考的是运算符的行为console.log(1 2 2); console.log(1 2 2); console.log(1 2 2); console.log(1 2);这题本质上考的是当两边有字符串时执行字符串拼接但一元加号会先把操作数转成数字。我见过不少人在1 2 2这里卡住因为它等价于1 (2) 2即1 2 2结果是32而不是122或32。2.2 事件循环与异步输出顺序必考且必错异步编程是腾讯音乐这批笔试的重头戏几乎每套题里都会出现两三道变体。核心考点集中在事件循环Event Loop的执行顺序、微任务与宏任务的优先级、以及Promise链式调用的行为。我记得有一道很经典的输出顺序题console.log(start); setTimeout(() { console.log(timeout1); Promise.resolve().then(() { console.log(promise1); }); }, 0); Promise.resolve().then(() { console.log(promise2); setTimeout(() { console.log(timeout2); }, 0); }); console.log(end);这道题的输出顺序是start - end - promise2 - timeout1 - promise1 - timeout2。很多人在promise2和timeout1的顺序上就栽了。核心原因没搞明白微任务队列的清空时机是在当前宏任务结束之后、下一个宏任务开始之前。所以当同步代码执行完毕事件循环会先把微任务队列promise2清空然后再取出宏任务队列里的timeout1执行。而在执行timeout1的过程中产生了新的微任务promise1这个微任务会在当前宏任务结束之后立刻执行而timeout2作为宏任务排在最后。这类题要想不出错关键要建立一张流程图在脑子里同步代码 - 清空微任务 - 执行一个宏任务 - 再清空微任务 - 执行下一个宏任务。反复用这个模型去套就不会乱。除了输出顺序题还有一道考Promise状态流转的题也让人记忆犹新const p new Promise((resolve, reject) { console.log(executor); resolve(success); console.log(after resolve); reject(error); }); p.then(res console.log(res)).catch(err console.log(err));这道题考察两个知识点第一Promise的executor是同步执行的第二Promise的状态一旦从pending变成fulfilled或rejected就不能再改变。所以console.log(executor)和console.log(after resolve)都会同步输出resolve(success)后面的reject(error)不会影响状态最终只有then里的回调被执行。2.3 那些容易被忽略的JS小考点剩余参数、原型链与闭包腾讯音乐这批笔试里还考了一些平时写业务代码时不太会留意的知识点但恰恰是这些知识点区分了“会写代码”和“懂JavaScript”两种人。剩余参数rest parameters相关的一道题让我印象很深因为网上搜“前端开发 函数 ...arg”能搜出一堆相关讨论这确实是个热门考点function test(...args) { console.log(args); console.log(arguments); console.log(Array.isArray(args)); console.log(Array.isArray(arguments)); } test(1, 2, 3);这里args是一个真正的数组而arguments是类数组对象。区别在于数组可以调用map、filter、reduce等方法而arguments需要先转换Array.from或展开运算符才能使用这些方法。另外箭头函数没有自己的arguments如果在箭头函数里访问arguments拿到的其实是外层普通函数的arguments。这些都是极容易被忽略的细节但在笔试里就是考察点。闭包的题目也很有代表性。腾讯音乐的风格不是直接让你说“什么是闭包”而是给你一段代码让你分析作用域链和变量生命周期for (var i 0; i 5; i) { setTimeout(() console.log(i), 1000); }这题答案是5 5 5 5 5。考的是var没有块级作用域循环结束后i已经变成5所有setTimeout回调共享同一个i。如果要输出0 1 2 3 4可以用let声明或者用闭包包裹一层(j () console.log(j))(i)。原型链的题考察了构造函数、实例和原型之间的关系function Person(name) { this.name name; } Person.prototype.sayName function() { console.log(this.name); }; const p new Person(Tom); console.log(p instanceof Person); console.log(p instanceof Object); console.log(p.constructor Person);这题本身不难但延伸出来的变体才是重点。比如如果执行了Person.prototype { ... }那p.constructor指向谁答案是Object因为constructor是从原型上继承下来的属性你把整个原型对象替换掉相当于把原来的constructor也丢了。这个知识点在Vue 2的响应式原理里也有体现属于典型的“笔试考基础、实际开发靠框架”的隐性连接。3. 三道编程题拆解从“似曾相识”到“真正拉开差距”3.1 第一道数组与字符串处理考察基本功第一道编程题一般不会太难腾讯音乐这批笔试的第一题是数组扁平化加去重排序的综合题题目大意是输入一个多维数组里面的元素可能是数字、字符串、也有可能是嵌套的数组请实现一个函数把所有元素提取出来去除重复项然后按照升序排序输出。function flattenAndSort(arr) { const flat arr.flat(Infinity); const unique [...new Set(flat)]; return unique.sort((a, b) a - b); }如果你对ES6新特性够熟直接调用内置API就能解决。但我猜测出题人想看到的不是这个而是你是否理解手写扁平化的逻辑。我实际提交的答案是这样的function flattenAndSort(arr) { const result []; const seen new Set(); const dfs (item) { if (Array.isArray(item)) { item.forEach(dfs); } else { if (!seen.has(item)) { seen.add(item); result.push(item); } } }; dfs(arr); return result.sort((a, b) a - b); }在笔试环境里arr.flat(Infinity)这种写法没问题但如果你不确定牛客网的运行环境是否支持新语法手写dfs递归更稳妥。另外排序一定记得传比较函数否则数字会按字符串顺序排比如[1, 10, 2]会变成[1, 10, 2]而不是[1, 2, 10]这个细节很多人会忽略。3.2 第二道手写防抖节流考察代码设计能力第二道题我记得是手写防抖debounce函数。这道题看起来简单但要求支持leading立即执行选项这就加大了难度。基础版防抖很多人会写function debounce(fn, delay) { let timer null; return function(...args) { clearTimeout(timer); timer setTimeout(() { fn.apply(this, args); }, delay); }; }但如果要求支持leading即第一次调用立即执行后续在等待期内不执行那就要额外处理标志位function debounce(fn, delay, leading false) { let timer null; let shouldCall leading; return function(...args) { const context this; if (timer) clearTimeout(timer); if (shouldCall) { fn.apply(context, args); shouldCall false; timer setTimeout(() { timer null; shouldCall leading; }, delay); } else { timer setTimeout(() { fn.apply(context, args); shouldCall leading; }, delay); } }; }这道题的关键不只是写出防抖的逻辑更在于你是否正确处理了this指向和参数透传。我发现很多候选人写闭包函数时用的是箭头函数导致this指向外层而不是调用者这在笔试里是很致命的。写这类题还有一个通用经验先写好基础功能再考虑边界情况。比如延迟时间是否为0、fn是否返回Promise等这些虽然不会在笔试里显式考察但展示了你的代码设计思维。3.3 第三道算法题时间复杂度和边界条件同样重要第三道题是一道字符串相关的中等难度题大意是给定一个字符串找出其中不含重复字符的最长子串长度。这题标准的解法是滑动窗口Sliding Windowfunction lengthOfLongestSubstring(s) { const map new Map(); let maxLen 0; let left 0; for (let right 0; right s.length; right) { const char s[right]; if (map.has(char) map.get(char) left) { left map.get(char) 1; } map.set(char, right); maxLen Math.max(maxLen, right - left 1); } return maxLen; }这道题有几个细节值得注意第一map.get(char) left这个条件不能少因为可能出现重复字符的位置在窗口左侧之外的情况这时候不需要移动left。第二时间复杂度是O(n)空间复杂度是O(m)其中m是字符集大小这在面试官追问时是必须能答上来的。第三边界情况是空字符串返回0全相同字符返回1。我见过不少人在这个题上翻车不是因为解法不会而是因为没考虑空字符串或者left移动的逻辑少了 left的判断导致结果偏大。笔试环境往往只给你几个测试用例不会把所有边界情况都列出来所以提交前务必自己在脑子里过一遍边界条件。4. 框架与工程化Vue规范、组件通信与代码设计4.1 Vue响应式原理从“会写”到“懂得为什么”腾讯音乐这套笔试的选择题里出现了好几道Vue相关题目重点集中在响应式原理和组件通信上。有一道题考察的是Vue 2中Object.defineProperty的局限题目大意是以下哪些操作无法被Vue 2的响应式系统自动侦测到选项包括直接通过索引修改数组元素、添加新的对象属性、使用push修改数组长度、修改已有属性的值。答案是直接通过索引修改数组元素、添加新的对象属性。因为Object.defineProperty只能拦截已有属性的getter/setter对于新增属性无能为力而数组索引的修改Vue 2对数组的拦截是通过重写方法实现的索引直接赋值无法触发更新。到了Vue 3Proxy可以从根本上解决这个问题因为它可以拦截对对象本身的任何操作包括新增属性、删除属性、访问不存在的属性等。这道题考察的其实是“你理解框架的原理而不是仅仅会用”。我自己的经验是准备这类题目时光记住结论是不够的要能画出Object.defineProperty和Proxy的对比图知道各自的拦截能力边界。因为面试官往往会在笔试之后追问细节比如“Vue 3为什么用Proxy替代defineProperty”“Proxy解决了defineProperty的哪些痛点”等。4.2 组件通信与代码规范笔试里的“软实力”考题除了原理题腾讯音乐还考了几道组件通信和工程规范相关的题目。有一道题是父组件往子组件传数据子组件想修改这个数据以下哪种做法是正确的这种题考察的是单向数据流的理解答案显然是子组件不能直接修改props应该通过$emit触发事件让父组件修改或者使用v-model。还有一道关于开发规范的题问的是在团队项目中使用Git以下哪种提交信息格式是最推荐的从选项来看显然要选择那种清晰描述改动类型的格式比如feat(login): 增加登录表单校验逻辑而不是update code或fix bug。这其实反映了大厂对代码可维护性的重视。关于“前端开发规范vue”这类热门搜索词也出现在了我当时的准备清单里。腾讯音乐的笔试虽没有直接考ESLint配置细节但在编程题中代码的可读性和规范性会被人工评阅阶段重点关注。我建议提前看一下Vue官方风格指南特别是组件命名、props定义、emit事件命名的推荐做法这些看似琐碎的点在实际笔试和面试中都很容易遇到。5. 笔试中的坑点和时间分配这些教训值一张复活卡5.1 我踩过的坑超时、边界条件和“没看清题”实话说我第一套模拟题做下来成绩并不理想复盘时发现了三个明显的坑。第一个坑是时间分配不合理。选择题虽然是低分项但我耗了太多时间在纠结某道类型转换题上导致后面编程题时间不够第一道题还没优化就直接提交了。后来我给自己定了个规矩选择题单题超过两分钟就先蒙一个标个记号回头有时间再细想编程题留出至少60分钟的大块时间。第二个坑是边界条件。编程题不是只测试通过用例就行牛客网的系统会跑很多隐藏用例。比如第二道手写防抖的题我一开始没考虑leading为true时的逻辑结果只能部分通过。好的习惯是提交前先在脑海里列出边界空输入、极端长度、重复元素、全相同元素等逐一自测。第三个坑是没看清题。我记得有一道选择题问的是“以下哪些选项不能被Vue侦测到”我当成了“哪些能被侦测到”完全是反向选择。这种低级错误极其可惜唯一的解法就是审题时圈出关键词比如“不能”“错误”“不属于”等否定词。5.2 从这次笔试反推的推荐时间分配策略经过反复测试和复盘我总结了一套适合腾讯音乐这批笔试题型的时间分配方案供参考时间段任务建议时长开考后0-25分钟快速完成所有选择题标记不确定的题25分钟25-35分钟回头检查标记的选择题实在不会就靠第一感觉10分钟35-60分钟完成第一、二道编程题确保基础功能正确25分钟60-100分钟攻克第三道算法题先写暴力解再优化40分钟100-120分钟整体检查补边界条件检查代码格式20分钟这套方案的核心思路是宁可放弃一道难题的完美解也不能让简单题因为没时间检查而丢了分。笔试本质上是有限时间内的资源分配你不需要拿到满分只需要超过大多数人。6. 备考路线与应试策略从这套笔试反推的准备方向6.1 按知识点分层的准备路线如果你准备参加腾讯音乐下一批春招笔试我的建议是不要直接刷题而是先按知识点分层建立自己的知识框架。第一层是JavaScript语言核心。把类型转换规则、作用域与闭包、this指向、原型链、事件循环这五个板块彻底吃透。每家公司的笔试都会从这几个板块抽题越熟练越好。推荐去翻一遍MDN上关于和的比较算法、Object.defineProperty的文档以及Promise/A规范这些是第一手资料。第二层是框架原理。Vue重点看响应式原理、生命周期、组件通信React重点看hooks原理、状态管理、渲染优化。不要在“API怎么用”上花太多时间要去看“为什么这么设计”。第三层是算法与数据结构。不必追求把所有hard题都刷完但滑动窗口、双指针、动态规划的基础题、字符串处理、数组操作这些类型必须熟练。腾讯音乐的笔试难度大概在LeetCode中等题偏下重点是把常见的解题模板背熟做到条件反射。除了技术知识还有一点容易被忽视熟悉笔试平台的操作。牛客网的代码编辑器、调试方式、提交逻辑和本地IDE差别不小建议提前用牛客网做几套模拟题把环境问题提前暴露掉。6.2 我个人建议的刷题与复盘顺序笔试准备是一个相对漫长的过程我自己的经验是分三个阶段推进。第一阶段基础扫盲大约一周。用两到三天把JavaScript核心知识点过一遍重点做类型转换、事件循环、闭包、原型链的选择题和简答题。再用两到三天刷Vue和React的原理题。这个阶段不需要追求速度关键是理解。第二阶段编程题专项大约两周。每天做两道编程题一道算法题一道手写题。算法题严格按照“读题-想思路-写代码-测边界-复盘”的流程走手写题重点关注防抖、节流、深拷贝、数组去重、Promise.all等高频考点。刷完的题一定要整理到笔记里把错误原因和优化思路记录下来。第三阶段模拟冲刺大约三到五天。每天做一套完整的模拟卷严格按照真实考试的时间限制和节奏来。做完之后不要只看分数逐题复盘错因是知识盲区、审题不清还是紧张导致失误把高频错因记录下来在考前反复提醒自己。我在这个阶段还有一个个人习惯把错题按“概念模糊”“思路错误”“边界遗漏”分类整理考前只翻这些错题。这样既不浪费时间重复刷已经会的题又能精准补弱。腾讯音乐这批笔试给我最深的感受是大厂前端笔试越来越不满足于“你能写出能跑的代码”而是更看重你“是否理解代码背后的原理”。那些看起来简单的选择题往往是整个笔试中最能拉分的部分。准备过程中别怕麻烦把每个知识点都往深处多问自己一句“为什么”到了考场上你会感谢当时的自己。
返回列表