
1. 笔试全景一场时效两年的“技术面试前哨战”每年秋招都是场硬仗尤其是提前批。Shopee的2024届秋招提前批前端岗位我是在7月中旬投递的简历大概一周后就收到了笔试邀请。跟很多大厂一样提前批的笔试安排在正式批之前题量和难度通常会卡在“筛选真正能动手写代码的人”这条线上不会像正式批那样略微放水所以准备方向要更偏实打实的编码能力而不是背八股。先说整体感受。整场笔试时长两个小时系统是牛客网那套在线编译器题型分两块一块是前端基础选择题和简答题另一块是两道算法编程题。跟一些传统大厂动辄四五道算法题不同Shopee的笔试更看重综合能力前端基础题的分量不低甚至有些题考得非常细比如事件循环的输出顺序、CSS层叠上下文、HTTP缓存头的优先级这类很容易被忽略的角落。如果你只是疯狂刷LeetCode而忽略了前端基础可能会在选择题上吃亏。再说说这套笔试适合谁参考。如果你是准备投递Shopee前端岗位、或者计划参加东南亚电商类公司秋招的同学这篇文章里的考点复盘和做题策略可以直接拿去做清单。如果你只是对前端笔试的题型风格好奇也可以大概了解下现在头部互联网公司在前端筛选时关注哪些能力点。项目背景关键词Shopee秋招、FE岗、提前批笔试 笔试平台牛客网在线IDE 时长120分钟 题型前端基础选择/简答 算法编程接下来的内容我会按时间线把整场笔试拆开讲从题型结构到每类题的具体考点再到我在做题过程中的策略和踩坑点最后统一整理成一个可以直接用的备战清单。2. 核心考点复盘前端基础与工程化实战2.1 HTML/CSS/JavaScript基础这些角落题最容易翻车前端笔试的第一部分通常是基础选择题范围覆盖HTML、CSS、JavaScript、浏览器原理、网络协议等。这部分题量大、单题分值低但正因为“单题看起来简单”很多同学反而在这里栽跟头。我复盘了一下发现Shopee的题目风格偏“实战导向”不是那种死记硬背就能答对的教科书题而是会给你一段代码或一个具体的页面场景让你判断输出或选择最优方案。举例来说有一道题考了事件循环的输出顺序我当时印象很深因为代码里混合了setTimeout、Promise.resolve().then、async/await以及一个requestAnimationFrame回调。这种题白纸黑字看起来不难但实际执行顺序涉及到“宏任务队列、微任务队列、渲染帧前回调”三个时间维度的交叉非常容易错。如果你想系统准备建议把事件循环的每一步画成时间线尤其是await之后的代码相当于被包进了一个.then这个语义很多人容易记混。还有一道CSS题是关于层叠上下文的。题干给你一个父容器设置了opacity: 0.5里面两个子元素分别设置了z-index: 999和z-index: -1问你哪个元素绘制在最上面。如果不知道opacity小于1会创建层叠上下文这道题基本就废了因为你可能会被z-index的数字大小带偏。这种题属于“知道原理就秒答不知道就完全靠猜”的类型复习的时候要重点记住z-index只有在同一个层叠上下文里才比较大小opacity、transform、filter等属性都会创建新的层叠上下文。HTML部分虽然没有考特别偏门的标签但有一题问到了img的loadinglazy属性和script的async、defer区别。这些都属于日常开发里最常用的优化手段不算超纲。但值得一提的是有一道多选题问“哪些操作会引起页面回流reflow”选项里有修改width、读取offsetHeight、修改display、修改color。很多人可能会漏选“读取offsetHeight”因为读取操作本身不会直接引起回流但浏览器为了拿到准确的布局信息会强制同步执行一次回流这个在性能优化里是特别典型的坑。注意基础题里真正的拉分项不是那些“偏题怪题”而是“你天天在用、但从来没细想过原理”的题。复习重点应该放在事件循环的完整机制、层叠上下文、缓存策略、Promise与async/await的语义边界这几个方向上。2.2 框架与工程化从组件通信到构建性能Shopee前端团队主要技术栈是React所以笔试题里React的内容占比明显高于Vue。不过他们不是只问生命周期函数这种背多分题目而是会结合具体业务场景让你做方案选择。我记得有一道场景题是一个列表页面列表项有数千条数据每项可以展开查看详情展开时会有一次异步请求。要求设计一个性能最优的方案。选项里有直接在组件里setState、用useState加useMemo、用React.memo包裹列表项、用虚拟列表。这题其实考的是“渲染性能优化”的综合理解不是单一API题。如果你的知识储备里只有“React.memo可以避免重复渲染”那你很难回答好它因为真正需要注意的还有“请求竞态”问题。列表展开时如果用户快速切换多个展开项后发请求可能先返回导致页面显示错误数据这时候需要在组件卸载或依赖变化时丢弃旧请求的结果。另外还有一道比较偏工程化的题问的是Webpack构建产物体积优化给了几个方案SplitChunksPlugin拆分公共依赖、tree-shaking开启、babel-loader开启缓存、资源压缩。这道题表面问“哪些能减小打包体积”实际上还埋了一个坑babel-loader缓存只影响构建速度不影响产物体积。如果你把缓存也选成“减小体积”那就错了。这种题就是典型的“工程化常识题”没有系统做过项目优化的人很难答全。工程化方面还有一道关于模块联邦的题这让我有点意外因为模块联邦虽然是Webpack 5的重要特性但在校招笔试里出现频率不算高。题干是微前端场景下的模块共享方案给了一个ModuleFederationPlugin的配置问你远程模块加载失败时的兜底处理。这道题我做得一般因为平时项目里并没有真正落地过微前端只是看过一些原理文章。所以面试准备期间模块联邦、ESM远程加载、沙箱隔离这些偏“现代工程化”的概念还是要认真看一遍尤其是它们能解决什么业务问题、有哪些局限性这类概述性的理解就够应付笔试了。2.3 网络与浏览器缓存、跨域、安全一个不少网络部分的题目数量不多但分值都很扎实而且和日常开发高度绑定。有一道题是根据一个HTTP响应头判断资源会被缓存多久响应头里有Cache-Control: max-age3600、ETag、Last-Modified、没有Expires。这个考察点比较基础但稍微变一下就会难很多比如加上no-cache或must-revalidate之后语义就不一样了。我建议大家把缓存相关的响应头画成一个决策树按优先级从高到低排一遍笔试时直接套用。跨域部分考了一道“如何解决CORS跨域请求带上Cookie”的问题。如果你只是背过Access-Control-Allow-Origin: *那这道题就踩坑了。带Cookie的跨域请求要求Access-Control-Allow-Origin必须指定具体源不能是通配符同时前端请求需要设置credentials: include后端还需要配置Access-Control-Allow-Credentials: true。这题考察的是CORS预检流程和Cookie跨域策略的配合属于“知道就是送分题、不知道就是送命题”的典型代表。安全方面有一道XSS的题目问哪种方式可以有效防御XSS攻击。选项有对用户输入做HTML实体编码、使用CSPContent Security Policy限制脚本来源、使用HttpOnly的Cookie、对用户输入做SQL参数化。前三个都对最后一个跟SQL注入有关不解决XSS问题。这种题对做了完整前端项目的同学来说不难但如果是只刷算法的同学可能会在CSP这个选项上犹豫。3. 算法与数据结构笔试的硬骨头3.1 题型分布与难度梯队算法编程题是Shopee笔试的重头戏两道题占据的分值应该在一半左右。如果你算法题一道都没做出来即使前面的基础题全对也很难通过。从难度上看第一题通常是中等偏简单第二题在中等偏难上下浮动风格比较贴近“业务场景包装后的经典题”不是纯模板题。第一道题是“给定一个数组找出所有和为target的不重复三元组”。这个就是LeetCode 15题的变体难度不算高主要考察排序加双指针。你只要提前刷过“两数之和”和“三数之和”系列基本十分钟内就能写出来。这里有个细节题目要求不重复三元组所以去重逻辑要写对不能只对数组排序去重因为数组中可能本身就有重复元素。正确做法是在双指针移动时跳过相同值并且外层循环里遇到和前一个相同的数字也要跳过。第二道题是“二叉树的最大路径和”变体但不是LeetCode 124的原题。题干稍微改了一下路径不仅可以从任意节点出发到任意节点结束还允许经过根节点到另一棵子树的任意节点但路径上不能有重复节点。其实这个限制条件等价于“路径不能分叉”那就回到了原题的核心逻辑递归计算左右子树提供的最大贡献值负数直接丢弃用全局变量记录当前节点作为连接点时能得到的最大值。两道题都算经典题型只要系统刷过LeetCode热题100和剑指Offer基本都能稳定AC。但对于准备时间有限的同学我建议按“数组 → 双指针 → 二叉树 → 动态规划”这个优先级准备从Shopee真题风向来看这个顺序性价比最高。3.2 高频题型的解题思路与时序复杂度分析先说“三数之和”这道题。整体思路是固定一个数然后用双指针找剩下两个数。排序的时间复杂度是O(n log n)双指针过程是O(n)外层循环是O(n)所以整体是O(n²)。笔试时一般不会要求你写出严格的复杂度证明但会在代码注释里要求标注所以一定要知道自己写的是什么复杂度。我当时是这样写的function threeSum(nums, target) { nums.sort((a, b) a - b); const res []; for (let i 0; i nums.length - 2; i) { if (i 0 nums[i] nums[i - 1]) continue; let left i 1; let right nums.length - 1; while (left right) { const sum nums[i] nums[left] nums[right]; if (sum target) { res.push([nums[i], nums[left], nums[right]]); while (left right nums[left] nums[left 1]) left; while (left right nums[right] nums[right - 1]) right--; left; right--; } else if (sum target) { left; } else { right--; } } } return res; }这里最关键的技巧就是三个while去重。笔试时如果漏写了这两个内部while遇到重复元素多的用例时可能会输出重复三元组导致部分用例不通过。我当时就是因为只写了外层去重、没写内层去重跑测试用例时差了一组debug了两分钟才发现。“二叉树最大路径和”这边的写法更考验递归思维。核心是每个节点要返回“从当前节点向下走能得到的最大单边贡献值”同时用一个全局变量记录“以当前节点为路径最高点时的最大路径和”。单边贡献值为负数时直接丢弃因为“尽量不加”比“加一个负数”更优function maxPathSum(root) { let max -Infinity; function dfs(node) { if (!node) return 0; const left Math.max(0, dfs(node.left)); const right Math.max(0, dfs(node.right)); max Math.max(max, node.val left right); return node.val Math.max(left, right); } dfs(root); return max; }这类题在笔试题里出现频率很高因为递归代码量短、思路优雅能同时考察你对二叉树的遍历方式、递归返回值设计和全局状态管理三个维度的掌握程度。3.3 刷题策略与错题本方法很多同学在准备大厂笔试时喜欢闷头刷题一天刷个十几道刷完就忘。我个人不太推荐这种方式。笔试准备更像是一个“题型识别 → 套路记忆 → 条件反射”的过程而不是“题海战术”的过程。我当时给自己定的目标是LeetCode热题100刷两遍第一遍按标签刷第二遍乱序刷。按标签刷的意义在于建立“看到题目特征就知道用什么数据结构”的直觉比如看到“最大/最小窗口”想到滑动窗口看到“前缀和”想到哈希表优化看到“TopK”想到堆或快速选择。乱序刷则是为了模拟考试状态因为你不知道下一道题会考什么。错题本的用法也很有讲究。我不建议把整道题的代码贴进去而是记录三句话题目特征比如“有序数组去重”——双指针、思路一句话固定一个点剩余用双指针逼近、易错点外层循环去重内层双指针去重。这样复习的时候每道题最多三十秒就能过一遍效率很高。4. 被误解的搜索热词前端FE与Doris FE/BE的关系辨析4.1 为什么你会搜到“doris fe和be”在准备Shopee前端笔试时你可能像我一样顺手搜索过“Shopee FE”这个关键词结果跳出来的搜索结果里夹杂了不少“doris fe和be”的内容。这其实是一个典型的名词混淆在电商后端架构里Doris是一个开源的实时数据仓库它把节点分为FEFrontend和BEBackend而在前端招聘语境里FE指的是Frontend Engineer。两个“FE”只是缩写恰好相同本质上完全是两个领域的东西。这个混淆对笔试准备的影响不大但也能反映出一个问题你在查资料时要学会区分搜索结果的语境。如果你搜“FE是什么”想看前端岗位要求结果打开一篇Doris架构文档那大概率会浪费时间。建议搜索时加上“前端”或“校招笔试”这类限定词能有效过滤掉后端和大数据方向的干扰信息。4.2 Doris FE/BE到底代表什么Doris的FE全称是Frontend负责SQL解析、查询规划、元数据管理和集群协调之类的读路径控制面工作BE全称是Backend负责数据存储和查询执行是真正的存算引擎。如果拿餐厅类比FE是前台点单员和后厨调度中心负责记录订单、安排流程BE是灶台上真正炒菜的师傅。FE不直接接触数据但负责告诉数据去哪个BE节点执行。对前端同学来说了解这些不一定是笔试必需但如果你投递的是Shopee这种电商公司它家的数据报表、商家后台、搜索排序这些场景里都可能用Doris或类似OLAP引擎。面试聊项目时如果你能提到“前端页面性能优化需要后端的查询链路配合比如用Doris加速数据汇总查询”这反而是加分项。不过笔试环节不会考这些东西不用过度纠结。4.3 “Doris FE下images文件夹”这个问题的由来与正确答案还有一个搜索词很有意思“doris fe下images文件夹是做啥的”。搜索这个的同学大概率是把“FE”理解为“前端工程”了于是好奇前端工程里为什么会有一个存放图片的文件夹。但在Doris的源码目录结构里fe/目录下放的是Java后端代码不是前端静态资源。严格来说Doris FE的Web UI模块里确实有一个webroot目录用来存放自带的监控和管理页面资源里面会包含static、images之类的子目录这些图片主要是Doris集群管理界面里用到的logo、图表、favicon等静态素材。也就是说如果你在某个Doris FE节点的部署路径里看到了images文件夹那多半是从webroot里释放出来的目的是给自带的Web监控页面提供样式和图片资源。这个问题本身很冷门大概率不是面试考点。但它提醒我们一件事看到陌生目录结构时不要先入为主地用“前端/后端”的二分法去套而是要结合它所在的工程上下文去判断。这个排查思路在笔试做“代码文件结构题”时也很有用。5. 实操方法与答题策略从审题到通过的完整链路5.1 编程题的标准化答题流程编程题这部分我有一套自己习惯的流程能有效降低“代码写一半发现思路不对”的概率。第一步是花两到三分钟读题把题目里的关键约束抽出来数据范围决定时间复杂度上限、输入输出格式决定怎么处理边界、是否要求去重/排序决定要不要额外处理。第二步是“先讲思路再动手”。牛客网在线IDE有白板或代码区你可以在代码注释里先写下整体思路比如“先用哈希表统计频率再用小顶堆维护前K个高频元素”。这样做的好处是万一代码写到一半没时间了面试官在后台看代码时还能看到你的思路至少能拿过程分。第三步是“从暴力解开始再优化”。如果一时想不出最优解法不要卡在那里先把暴力解写出来保证至少能过样例。笔试的时间是有限的一道题卡十分钟以上就大概率做不完了。我在实际笔试中就遇到过这种情况第二道题一开始没想到递归里的负数截断逻辑先写了一个暴力回溯样例过了再改成递归节省了大量尝试时间。第四步是“自测边界用例”。笔试时最怕的不是不会做而是代码在核心用例上跑通了但边界用例没过。常见的边界情况包括数组长度为1、输入为空、整数溢出、二叉树只有左子树或右子树。我每次写完代码都会用一到两分钟检查这些边界提交前再统一跑一次所有示例。5.2 简答题的答题技巧结构化表达是加分项基础简答题虽然每题分值不高但它是面试官了解你表达能力和逻辑思维的第一窗口。我在做简答题时会尽量按照“是什么 → 为什么 → 怎么做 → 有什么坑”的四段式来组织答案。比如面试官问“浏览器缓存策略”我不会只写Cache-Control是什么而会补充具体响应头到了浏览器后浏览器会先检查什么、再检查什么以及no-cache和no-store在实际业务中的推荐场景。有一个容易被忽略的点是简答题的作答框可能不是编辑器而是一个纯文本框你没法输入代码。这种时候不要硬贴代码而是用自然语言清晰地描述方案。如果确实需要说明代码逻辑可以写伪代码或者关键步骤的简短描述让阅读者能快速抓到你的思路。另外答题时注意控制篇幅。两三行就答完的答案显得太敷衍但写满一千字又会显得没有重点。一般情况下一道简答题控制在100到200字之间比较合适。核心就是“要点明确每个要点一句话解释就够了”。5.3 遇到完全不会的题怎么办笔试时遇到完全没思路的题心态最容易崩。我当时做了一个临时补救动作先把题目里所有能提取的条件列出来逐条分析它们能不能给算法优化提供线索。比如题目提到“数组是有序的”那大概率能双指针或二分提到“最多k次操作”那大概率是滑动窗口提到“返回所有可能的组合”那大概率是回溯。万一分析完还是不会那就老老实实写一个能过部分用例的暴力解并在注释里标明“这里可以优化但为了避免超时我用暴力解先保证正确性”。在真实笔试里不完全AC但用例过了一部分通常可以拿到比零分高得多的分数千万不要直接交白卷。6. 常见问题与排查技巧实录6.1 远程笔试环节摄像头、网络、浏览器一个都不能掉链子Shopee的提前批笔试是全程远程监控的考试系统要求开启摄像头并且不能切出浏览器页面。我提前一天做了环境测试结果发现宿舍的WiFi在晚高峰时丢包率很高后来借了室友的网线接口改成了有线网络才稳定。这个细节看着不起眼但真正考试时如果网络抖动导致代码提交失败心态会瞬间崩掉。另外有几个浏览器层面的坑需要提前排除一是关闭所有广告拦截插件有些广告拦截插件会误伤在线IDE的脚本二是不要开翻译插件因为翻译插件自动把英文界面翻译成中文后代码编辑器里的一些变量名可能会被错误处理三是提前确认浏览器版本满足考试系统要求最好用考试推荐的最新版Chrome或Edge。6.2 样例通过但提交不过怎么办笔试中最磨人的情况是本地和在线IDE上跑题目的示例用例全部通过但提交后提示“通过率0%”。这种时候不要慌按概率从高到低排查几个点。第一检查输入解析。在线IDE一般不会给你处理输入输出的模板你需要自己写readline或fs模块的读取逻辑。输入格式少读一行、多读一个空格都会导致全部用例失败。我在一道题的实现里就掉进了这个坑题目说了有多组输入我用了一次readline只取了一行结果只过了第一个用例。第二检查输出格式。题目要求输出的分隔符是空格还是逗号、末尾是否允许换行这些细节都会影响结果。特别是当题目要求输出数组时很多人习惯输出[1,2,3]但题目要求的格式是1 2 3。第三检查是否有额外的排序要求。比如“输出所有不重复组合顺序不重要”和“输出按字典序排列的所有组合”是完全不同的要求。如果题目没明说但示例暗示了排序而你代码里没有排序就会遭遇示例通过但提交失败。6.3 笔试后的复盘与后续流程笔试结束后不要立刻把题目忘掉趁热打铁复盘才是最有价值的动作。我会在笔试结束后半小时内把每一道题的题目描述、我的解法、出错点、以及最优解思路记录下来。这样做的好处是面试环节如果被问到“你印象最深的一道题”你可以拿出来完整地讲思路和踩坑过程这比临时回忆要靠谱得多。关于后续流程Shopee的提前批笔试通过后一般会在两周左右收到面试通知。面试通常分两到三轮技术面加一轮HR面技术面里大概率会让你讲项目也可能会接着笔试题目问一些扩展问题。比如你笔试里写了一个递归解法面试官可能会问“这个递归调用栈深度会不会有问题”“能不能改成迭代实现”。所以笔试复盘时不要只看自己写没写出来还要想想能不能优化。提示笔试后一周内多留意邮箱和短信Shopee的面试邀请大多通过邮件发送容易被垃圾箱拦截。我当时就是在垃圾箱里翻到了面试通知差一点错过。写在最后一点个人经验笔试是整个秋招流程里一个很奇妙的节点它不像简历那样可以反复打磨也不像面试那样有来回交流的机会更像是一场两小时的孤独极限运动。对我个人来说这次Shopee提前批笔试最大的收获不是拿到了面试机会而是让我意识到自己在事件循环细节和二叉树递归返回值设计上还有明显短板。如果你也在准备类似的笔试我的建议很简单基础题不要只背答案要沿着题面推演一遍完整原理算法题不要只追求AC要把“为什么用这个数据结构”“为什么这样去重”想清楚做题策略则是宁可用慢一点的思路先写对也不要卡在最优解里浪费太久。最后再分享一个笔试时的小技巧开考前五分钟先把草稿纸上写下自己容易忘记的要点比如await之后的代码相当于.then回调、z-index只在同层叠上下文里生效、输入解析要注意多组数据这样做到相关题目时扫一眼草稿纸就能快速提醒自己。这个小动作帮我避开了至少两个陷阱希望你也能用上。