当前位置: 首页 > ai >正文

腾讯前端面试模拟详解

以下是腾讯及腾讯音乐娱乐(TME)前端岗位高频手撕题目详解,结合真题及考察要点整理,覆盖面试核心考点:


⚙️ 一、核心手撕题(腾讯/TME 必考)

1. Promise 并发控制(90%场次出现)
  • 题目:手写 Promise.all(需处理错误短路、位置保持)
  • 核心思路
    • 校验输入为数组,空数组直接 resolve([])
    • 遍历 Promise 数组,用 Promise.resolve 包装非 Promise 值。
    • 计数完成量,全部成功时返回结果数组;任一失败立即 reject
  • 边界处理
    Promise.myAll = (promises) => {if (!Array.isArray(promises)) return Promise.reject(new TypeError('Argument must be an array'));let count = 0, results = [];return new Promise((resolve, reject) => {promises.forEach((p, i) => {Promise.resolve(p).then(res => {results[i] = res; // 保持结果位置if (++count === promises.length) resolve(results);}).catch(reject); // 短路逻辑});if (promises.length === 0) resolve(results);});
    };
    
2. 数组扁平化(80%场次出现)
  • 题目:实现多层嵌套数组降维(如 [1, [2, [3]]] → [1, 2, 3]
  • 方案对比
    • 递归法:深度优先遍历,遇到数组则递归展开。
    • flat API:直接调用 arr.flat(Infinity)(需注意浏览器兼容性)。
    • Reduce 递归
      const flatten = (arr) => arr.reduce((pre, cur) => pre.concat(Array.isArray(cur) ? flatten(cur) : cur), []);
      
3. 深拷贝(70%场次出现)
  • 考点:处理循环引用、特殊对象(Date/RegExp)
  • 代码关键点
    • 使用 WeakMap 缓存已拷贝对象,避免循环引用导致的栈溢出。
    • 特殊对象单独处理(如 new Date(obj))。
    function deepClone(obj, map = new WeakMap()) {if (obj === null || typeof obj !== 'object') return obj;if (map.has(obj)) return map.get(obj);const clone = obj instanceof Date ? new Date(obj) : obj instanceof RegExp ? new RegExp(obj): Array.isArray(obj) ? [] : {};map.set(obj, clone);Reflect.ownKeys(obj).forEach(key => {clone[key] = deepClone(obj[key], map);});return clone;
    }
    

⚡️ 二、特色场景题(腾讯音乐TME高频)

1. 页面通信与崩溃监控
  • 题目:从页面A打开页面B,B关闭(含崩溃)时通知A
  • 解决方案
    • 正常关闭:在B的 window.onbeforeunload 中通过 localStoragepostMessage 传参,A监听 storagemessage 事件。
    • 崩溃监控
      • B页面定时(5s)向Service Worker发送"心跳"。
      • Service Worker检测超时(15s无心跳)判定崩溃,通知A页面。
      // B页面心跳发送
      setInterval(() => navigator.serviceWorker.controller.postMessage({ type: 'heartbeat' }), 5000);
      // Service Worker检测逻辑
      if (Date.now() - lastHeartbeat > 15000) reportCrash();
      
2. 大数相加(校招重点)
  • 题目:实现超过JS精度限制的数字加法(如 "9999999999999999" + "1"
  • 思路
    • 字符串反转,按位相加并处理进位。
    • 注意高位补位(如最终进位不为0)。
    function addBigNumbers(a, b) {const arr1 = a.split('').reverse(), arr2 = b.split('').reverse();let result = [], carry = 0;for (let i = 0; i < Math.max(arr1.length, arr2.length); i++) {const sum = (parseInt(arr1[i] || 0) + parseInt(arr2[i] || 0) + carry);result.push(sum % 10);carry = Math.floor(sum / 10);}if (carry) result.push(carry);return result.reverse().join('');
    }
    
3. 二叉树遍历(基础算法)
  • 题目:实现二叉树前序/中序/后序遍历(递归与非递归)
  • 递归示例
    const preorder = (root, res = []) => {if (!root) return res;res.push(root.val);        // 前序:根左右preorder(root.left, res);preorder(root.right, res);return res;
    };
    

💡 三、答题技巧与避坑点

  1. 原理深挖
    • 腾讯必问实现逻辑(如 Promise.all 的并发控制、深拷贝的循环引用处理)。
    • 避免只答API用法(如被追问“flat 的内部实现”)。
  2. 边界处理
    • 空输入、极端用例(如大数相加的进位溢出)需显式处理。
  3. 工程化思维
    • 结合业务场景(如页面崩溃监控需说明Service Worker的独立线程特性)。

腾讯系面试注重原理实现深度场景落地能力,建议优先掌握以上高频题,并扩展练习虚拟DOM Diff、响应式原理(Proxy/defineProperty)等进阶题。


JavaScript 算法详解

1. 最大公共前缀

/*** 查找字符串数组中的最长公共前缀* @param {string[]} strs 字符串数组* @return {string} 最长公共前缀*/
function longestCommonPrefix(strs) {let res='';if(strs.length===0)return res;const val=strs[0];for(let i=0;i<val.length;i++){let curChar=val[i];for(let j=0;j<strs.length;j++){if(strs[j][i]!==curChar)return res;if(j===strs.length-1) res+=curChar;}}return res;
}// 示例
console.log(longestCommonPrefix(["flower","flow","flight"])); // "fl"
console.log(longestCommonPrefix(["dog","racecar","car"])); // ""

算法思路

  1. 如果数组为空,直接返回空字符串
  2. 以第一个字符串作为初始公共前缀
  3. 遍历数组中的每个字符串,与当前公共前缀进行比较
  4. 如果不匹配,则缩短公共前缀,直到匹配或变为空字符串
  5. 返回最终的公共前缀

2. 最大子序列和

/*** 查找数组中连续子序列的最大和(Kadane算法)* @param {number[]} nums 数字数组* @return {number} 最大子序列和*/
function maxSubArray(nums) {let max=Math.max(...arr);let curSum=0;for(let i=0;i<arr.length;i++){curSum+=arr[i];max=Math.max(curSum,max);if(curSum<0)curSum=0;}return max;
}// 示例
console.log(maxSubArray([-2,1,-3,4,-1,2,1,-5,4])); // 6 (对应子序列 [4,-1,2,1])
console.log(maxSubArray([-1,-2,-3])); // -1

算法思路(Kadane算法)

  1. 初始化当前最大值和全局最大值为第一个元素
  2. 遍历数组:
    • 对于每个元素,决定是将其加入当前子序列还是开始新的子序列
    • 更新全局最大值
  3. 返回全局最大值

3. 重复子字符串

/*** 判断字符串是否可以由它的一个子串重复多次构成* @param {string} s 输入字符串* @return {boolean} 是否可以由子串重复构成*/
function repeatedSubstringPattern(s) {// 将字符串与自身拼接,然后去掉首尾字符const doubled = s + s;const sliced = doubled.slice(1, -1);// 如果原字符串出现在拼接后的字符串中,则可以由子串重复构成return sliced.includes(s);
}// 示例
console.log(repeatedSubstringPattern("abab")); // true (可由 "ab" 重复构成)
console.log(repeatedSubstringPattern("aba")); // false
console.log(repeatedSubstringPattern("abcabcabc")); // true (可由 "abc" 重复构成)

算法思路

  1. 将原字符串与自身拼接
  2. 去掉拼接后字符串的首尾字符
  3. 如果原字符串出现在处理后的字符串中,则说明可以由子串重复构成
  4. 这种方法利用了字符串旋转和模式匹配的原理

数学解释

  • 如果一个字符串S可以由子串重复构成,那么S = n*sub
  • 将S+S = 2n*sub
  • 去掉首尾字符后,中间至少包含一个完整的S = n*sub
  • 因此S会出现在处理后的字符串中

这三个算法分别展示了字符串处理和动态规划的经典问题解决方案。

http://www.xdnf.cn/news/17547.html

相关文章:

  • 从零构建自定义Spring Boot Starter:打造你的专属开箱即用组件
  • 【linux】企业高性能web服务器
  • Horse3D引擎研发笔记(四):在QtOpenGL下仿three.js,封装EBO绘制四边形
  • HarmonyOS 开发入门 第一章
  • AI驱动的智能编码革命:从Copilot到全流程开发自动化
  • LAMPLNMP 最佳实践
  • 基于FPGA的热电偶测温数据采集系统,替代NI的产品(二)总体设计方案
  • Python Day27 HTML 核心知识笔记及例题分析
  • 【Kafka系列】第三篇| 在哪些场景下会选择使用 Kafka?
  • 自建Web应用防火墙(WAF)
  • React 19 通用 ECharts 组件
  • uni-app app端安卓和ios如何申请麦克风权限,唤起提醒弹框
  • 什么是网络准入控制系统?解析一款网络准入的详细功能
  • FPGA+护理:跨学科发展的探索(二)
  • 最短路问题从入门到负权最短路
  • 【算法专题训练】11、字符串中的变位词
  • “鱼书”深度学习进阶笔记(3)第四章
  • MLAG双活网络妙招:BGP + 静态VRRP实现智能负载均衡
  • (一)vscode搭建espidf环境
  • Linux线程——线程控制及理解
  • LLM大语言模型初步学习认识
  • day23|前端学习三件套
  • 集成电路学习:什么是URDF Parser统一机器人描述格式解析器
  • 10种经典学习方法的指令化应用
  • 动态创建可变对象:Python类工厂函数深度解析
  • 【k近邻】Kd树的构造与最近邻搜索算法
  • 用户虚拟地址空间布局
  • JVM管理数据的方式
  • 剧本杀小程序系统开发:推动行业数字化转型新动力
  • Linux中DNS系统搭建与配置指南(配实验步骤与注释)