
1. 这场笔试到底在考什么先看清商汤的选人逻辑聊这场笔试前得先弄明白商汤科技在你心里的画像到底是什么。2018年那会儿商汤正是AI视觉赛道最炙手可热的独角兽人脸识别、图像理解、自动驾驶这些标签都很响。很多人理所当然地以为去商汤做前端就是写几个管理后台、调调接口完事但实际拿到第二场笔试题的时候大部分人第一反应是这跟我想象的前端笔试完全不一样。商汤这类AI公司招前端本质上不是在招一个“写页面的人”而是在招一个“能理解算法产品怎么落地的人”。什么意思就是你的HTML/CSS功底要扎实JavaScript语言本身要吃得透同时你还得对Canvas、WebGL、数据可视化、甚至音视频处理这些偏图形学的前端方向有概念。因为AI公司的前端真正高频的场景不是电商大促页面而是标注工具、模型训练可视化平台、人脸比对演示系统、点云展示界面这类东西。我当时做完第二场笔试的整体感受是题目量不算变态但覆盖面极广而且考点选得很“刁”。刁不是指偏题怪题多而是它特别喜欢在一个看似基础的知识点上往下深挖两层专门试探你是真懂还是背过面试题。比如this指向、闭包内存、事件循环这些老生常谈的东西它换了个实际场景来考你你光背结论不分析过程很容易掉坑里。这篇文章我就以第二场笔试的复盘为主线把考点结构、典型题型、做题思路和备考方法完整拆一遍。不管你是准备校招还是想跳槽到AI视觉类公司这套前端知识体系的查漏补缺逻辑都适用。2. 考点全景拆解第二场笔试的知识地图与侧重点2.1 商汤前端笔试与普通互联网公司差异点先说差异。同样是校招前端笔试BAT的题目往往偏向工程化和业务化Promise实现、组件通信、性能优化方案、手写防抖节流这些东西在商汤的卷子里也会出现但占比不是最高的。商汤这场笔试的侧重点明显往三个方向倾斜一是JavaScript语言底层机制的精细理解二是Canvas/WebGL/可视化相关的前沿前端能力三是算法与数据结构的基础功底。前两点好理解和AI产品的形态强相关。第三点很多人会疑惑前端也考算法考而且考得不浅。商汤作为一家人工智能技术驱动型公司对于工程师的算法素养要求是全员性的不完全区分岗位。前端岗考算法不是说让你去训练模型而是考察你的逻辑抽象能力和代码实现能力。笔试里出现的算法题不会是动态规划难题但链表操作、二叉树遍历、字符串处理这类经典题是跑不掉的。还有一个明显的差异是商汤的笔试题目里会出现一些“带有业务场景包装”的题目。比如给你一个人脸框选交互的需求问你用原生Canvas怎么实现缩放和拖拽再比如给你一个模型训练日志的数据结构让你设计前端展示方案。这种题目考察的不只是API熟练度更是你面对一个不熟悉领域的拆解能力。2.2 核心知识模块权重分布参考如果给第二场笔试的知识模块排个优先级大致可以这样估算JavaScript语言核心含异步、原型、闭包、事件循环约占30%浏览器与网络基础渲染机制、缓存、HTTP约占15%CSS与页面布局布局方案、响应式、动画约占12%框架与工程化Vue/React、构建工具、模块化约占15%计算机基础与算法数据结构、复杂度、常见算法约占18%Canvas/WebGL/可视化及AI场景相关约占10%这个比例不是官方数据是我根据做题时的直观体感估的。但有一个信号很明显JavaScript和算法加起来接近一半权重说明这场笔试真正筛选的是“编程功底扎实”的人而不是“框架用得熟”的人。当时和我一起笔试的同学里有人Vue项目做了两三个结果栽在原型链和事件循环的题目上回头跟我复盘说感觉复习方向偏了。所以如果你打算去AI类公司做前端复习重心一定要往语言底层和算法基础倾斜。框架是工具随时可以换但对语言机制的理解、对编程基本功的掌握是短时间内补不回来的硬实力。3. 笔试题型实录与解题思路JavaScript部分3.1 this指向与调用方式最容易被绕晕的考点JavaScript部分的题目里this指向几乎是一定会出现的。第二场笔试里有一道很典型的题给你一段代码里面有普通函数调用、对象方法调用、箭头函数、setTimeout回调四种场景让你写出每次console.log的输出值。这道题表面考this实际考的是一整套规则默认绑定、隐式绑定、显式绑定、new绑定以及箭头函数不绑定this的机制。我做这道题时的分析顺序是这样的先看调用方式再看函数定义形式。普通函数直接调用非严格模式下this指向全局对象对象方法调用时this指向调用该方法的对象如果用了bind/call/applythis指向被绑定的对象如果是箭头函数则向上层作用域寻找this。顺序不能乱一乱就容易出错。这里有个很多人忽略的细节也是那年笔试的暗坑严格模式对默认绑定的影响。在严格模式下普通函数调用时this是undefined而不是全局对象。考题特意在代码顶部加了use strict如果不仔细看直接按非严格模式推算最后结果全错。3.2 原型链与继承别只会背结论商汤的笔试题很喜欢考原型链但不喜欢直接问你“原型链是什么”这种送分题。它会给你几个自定义构造函数让它们之间通过原型产生继承关系然后问你某个实例的某个属性查找路径是什么或者问instanceof的判断结果是什么。我当时遇到的一道题就是这样定义了一个父类Animal和一个子类Dog子类通过Dog.prototype new Animal()这种方式继承然后创建实例问实例.hasOwnProperty(name)和name in 实例这两个表达式分别返回什么。这道题的考点非常精准in操作符会沿着原型链查找属性而hasOwnProperty只检查自身属性。如果你理解了这两者的本质区别题目就是送分题如果只记结论不消化原理很容易掉坑。还有一道题是关于ES6 class继承的super调用顺序。在子类的constructor中super()必须在使用this之前调用否则会报错。笔试把它改成了一道判断题要求指出代码哪里会抛异常。这类题目其实在考察你平时写代码时有没有踩过类似的坑如果只写过组件没深究过类的机制可能会卡住。3.3 事件循环与异步微任务宏任务的实际执行顺序事件循环这道题几乎是2018年前后所有大厂前端笔试的标配商汤第二场也不例外。题目会给出一段混合了setTimeout、Promise、async/await的代码让你写出完整输出顺序。这类题在复习阶段必须自己动手画执行流程不能靠背。我当时候的分析方法是画两列一列是宏任务队列一列是微任务队列。脚本整体执行时同步代码直接在调用栈中执行遇到Promise的then回调就放进微任务队列遇到setTimeout就放进宏任务队列。微任务队列在每一轮宏任务结束后全部清空然后才执行下一个宏任务。用这个方法无论题目多复杂都能拆解清楚。但有一个坑我那年差点踩了async/await在底层是基于Promise实现的但await后面的代码并不是全部进入微任务队列的。在2018年那个时间点V8引擎对await的处理和现在也有细微差异。笔试时最好以标准为准默认await之后的代码作为微任务调度。如果不确定就在草稿纸上把Promise.resolve().then()的等价关系写出来再推导执行顺序。3.4 闭包与内存不只是概念题闭包这部分的考察方式第二场笔试里体现得很聪明。它没有直接问“什么是闭包”而是给了一个for循环配合setTimeout的经典场景问输出什么怎么改才能正确输出循环变量。这个题目考的知识点包括var/let作用域、闭包捕获、异步执行时机。标准答案大家都知道把var改成let或者用立即执行函数包一层。但笔试不止于此接着追加了一小问“上述两种改法在内存占用上有什么区别”这个追问就很有商汤风格了。用立即执行函数创建闭包每个闭包都持有循环变量的副本如果循环次数大内存占用更高用let则利用块级作用域实现上也是每轮新的绑定但不需要手动包裹函数语义更清晰。我当时做完这道题意识到商汤对JavaScript的考察是成体系的。它把作用域、闭包、异步、内存这几个知识点串在了一道题里如果你只掌握了分散的知识点而没有形成体系遇到这种综合题就很难拿全分。4. 笔试题型实录与解题思路浏览器、网络与CSS4.1 渲染机制与性能优化高频考点里的商汤特质浏览器渲染机制是第二场笔试中占比不小的部分核心考点集中在从输入URL到页面呈现的完整过程、浏览器的渲染管线解析HTML构建DOM、解析CSS构建CSSOM、合并生成渲染树、布局、绘制、合成、以及回流和重绘的概念与触发条件。我在刷题时总结了一套话术框架先说关键渲染路径的五个步骤再说每个步骤分别受什么因素影响最后引到性能优化的具体手段。例如CSS放在head中、JS放在body末尾并配合async/defer减少CSSOM和DOM的阻塞避免强制同步布局用transform代替top/left做动画以跳过布局阶段等。商汤在这块加了一道很实际的题目一个图像标注平台同时加载上百张高清底图页面卡顿严重问你从前端层面可以做什么优化。这个问题一看就是AI公司真实场景的映射。答案可以从图片懒加载、Canvas离屏渲染、虚拟滚动、Web Worker处理图像数据、压缩策略等多个维度展开。关键不是把每个方案都写详细而是让面试官看到你有针对性地分析问题瓶颈的能力。4.2 HTTP缓存GET和POST之外的必考知识点HTTP缓存属于前端笔试的基础送分题但商汤的特点是不会只问概念而是给你一个实际场景用户打开标注平台时底图资源大图和脚本资源如何设置缓存策略才合理。这个大题细分下来涉及强缓存和协商缓存两个层面。强缓存通过Cache-Control和Expires控制浏览器直接读取本地缓存不发请求协商缓存通过Last-Modified/ETag携带条件请求由服务器判断是否返回304。我在答题时画了一条时间线首次请求无缓存服务器返回200并带上Cache-Control和ETag第二次请求如果强缓存未过期直接命中不发请求过期后走协商缓存带If-None-Match字段服务器返回304浏览器继续使用本地缓存。关键话术要体现出两种缓存的适用场景。大图这一类非常稳定不经常变动的资源适合长强缓存而index.html这类入口文件更适合协商缓存或no-cache确保每次都能校验更新。4.3 CSS布局考点从浮动到Flex的过渡期考法2018年那会儿正好是Flexbox开始全面普及、但老项目还在用浮动的过渡期。商汤笔试里CSS布局的题目也比较有意思没有直接让你写三栏布局代码而是给了几个实际组件需求让你对比不同布局方案的优劣。其中有一道关于未知宽度元素水平垂直居中的题目。最稳妥的答案是flex布局但需要额外注意父级容器的高度设定。也可以用positiontransform: translate(-50%, -50%)的方式不依赖元素自身尺寸。还可以用grid布局代码更简洁但那年兼容性还有隐患生产环境使用需谨慎。商汤这类AI公司强调“你的方案是否适用于复杂业务场景”因为标注工具中经常需要处理父子组件、弹窗、拖拽浮层等复杂结构的居中问题。如果只会flex一种方案在某些需要兼容老内核浏览器或特定嵌入环境时可能不够用。所以笔试里它更看重你是否掌握多种方案并能说清取舍逻辑而不只是背一种标准答案。4.4 移动端适配从viewport到rem的完整链路移动端适配在商汤第二场笔试题中也有涉及。它给了一个场景公司要做一个移动端的人脸对比演示H5需要兼容不同尺寸的手机屏幕问你采用什么适配方案。我的答题思路是从viewport meta标签说起设置widthdevice-width, initial-scale1.0保证布局视口等于设备视口然后用rem方案通过动态设置html根元素的font-size将设计稿的px值按比例转换为rem对于1像素边框问题可以使用transform: scale(0.5)配合媒体查询处理也可以使用viewport的initial-scale按dpr整体缩放。最后补充一个现代思路vw/vh单位也可以做适配但考虑到部分低端Android机器对vw的兼容性问题实际项目里更稳妥的方案是rem为主、vw为辅或者直接用postcss-px-to-viewport这类工具在构建层面自动换算。这套组合和答题结构能看出你是有过真实移动端经验的而不是只背了概念。5. 框架与算法拉开差距的两大核心模块5.1 框架题的本质考的不是API是设计思想第二场笔试在框架部分的考察重点现在回头看非常有前瞻性。主流题库里背烂了的“beforeCreate和created的区别”“watch和computed的使用场景”这类题基本没出现反而把重心放在了框架的设计思想上。其中一道题在Vue中为什么不建议在v-for里同时使用v-if底层的设计原因是什么。这个题如果只答“性能不好”就太浅了至少要分析到v-for的优先级高于v-if所以即使某条数据不需要渲染v-if也会在每次迭代中被执行造成不必要的计算开销并且这种写法容易让人误以为v-if是逐个过滤后再渲染而实际上它是先渲染全部再逐个判断。正确做法是先用computed过滤出需要的列表再在模板中只做一次v-for遍历。还有一道关于React的题大意是setState之后究竟发生了什么。考察的是状态更新到UI渲染的整个流程setState会触发更新调度可能被合并批量处理然后走reconciliation流程对比虚拟DOM差异最终更新真实DOM。这个题目引导你把框架的核心机制说清楚而不是浮于表面。5.2 虚拟DOM与diff算法必问但很少有人能讲透商汤第二场笔试对虚拟DOM和diff算法的考察深入到了具体细节。题目并不直接问“什么是虚拟DOM”而是给了一个典型的列表更新场景要求描述diff算法如何对比新旧子节点列表。这时需要答出几个关键点首先diff算法默认采用同层对比不跨层级移动其次列表没有加key或key不稳定的情况下数组中的元素是怎么被逐个比较和复用的最后key的正确使用方式。最好能提到双端对比、首尾查找这类常见的diff优化策略并且指出key应当使用业务中唯一且稳定的ID而不是数组索引。作答时要避免纯背稿的感觉。我在复习时找了React源码里reconcileChildrenArray的实现思路来看理解比较策略的意图之后再回答这类题目就会自然很多。如果你能接一句“在Vue2中diff的复杂度做了很多优化Vue3中又引入了静态标记这种编译层面的提升”气氛会更好说明你是真的在用框架而不是停留在了解API的层面。5.3 算法题前端笔试的隐形门槛商汤第二场笔试算法题整体难度适中但想拿满分必须具备扎实的编码基本功。我印象里有几道题特别有代表性第一道是“反转链表”。这题本身不难但它要求用迭代和递归两种方式分别实现。递归版本如果对函数调用栈理解不透彻很容易写错边界条件。第二场里这道题放置在最后作为压轴不仅考察算法能力还考察代码能否一次编译通过。第二道是“字符串中的第一个唯一字符”。这题最简单的做法是哈希表记录每个字符出现次数再第二次遍历找到第一个出现次数为1的字符时间复杂度O(n)空间复杂度O(字母表大小)。这里要强调一下有笔试经验的人会写在哈希表里同时记录索引一次遍历就找到目标逻辑更紧凑一些。还有一道“合并两个有序数组”的变种题分别是两个排序好的数组要求合并后保持有序并要求在原数组上操作不使用额外空间。经典双指针从后往前遍历的解法一定得熟悉从尾部开始避免覆盖前面未处理的元素这是最容易被忽略的细节。5.4 手写代码的规范意识除了正确还要优雅手写代码题在商汤笔试中占比不低但相比结果正确它更看重代码的规范性和可读性。我当时在答题环境里写完代码后会再通读一遍重点检查变量命名是否有意义、是否存在多余的状态、边界条件是否处理完整。有一道在手写防抖函数时我还特意写了注释说明防抖的实现思路和触发时机。后来复盘时觉得这种习惯很加分因为笔试阅卷人通过代码看到的不仅是你能不能写出来更是你在真实团队里写代码的协作素养。函数命名要用动词或动词短语例如debounce、throttle、deepClone这类语义清晰的名称不要在笔试里写foo、bar这类占位符。关于手写题还有一个建议优先给出可读性好的版本再在注释里提优化空间。不要一开始就写一个充满花哨技巧但别人看不懂的版本。阅卷人看的是综合能力。6. AI场景硬核面Canvas、可视化与综合应用6.1 为什么AI公司前端必须懂Canvas和WebGL如果前面说的JavaScript、算法、框架是通用前端能力Canvas/WebGL和AI场景的结合才是商汤这类公司的差异化考点。笔试里有一道题直接问在Canvas中绘制一个可拖拽缩放的矩形标注框涉及哪些核心API与交互处理逻辑。这道题的作答框架应该是先获取Canvas的2D上下文对象用getBoundingClientRect计算鼠标坐标与Canvas坐标的映射在mousedown事件中记录起始点在mousemove中更新矩形宽高并调用clearRect清除画布后重新绘制在mouseup中结束绘制存储矩形数据。拖拽已存在标注框时需要先做点击区域的命中检测判断鼠标是否落在已有矩形内部。缩放会更复杂一些需要定义八个控制手柄命中后切换光标状态拖动时根据手柄方向更新矩形的x、y、width、height。这个流程基本就是标注工具的核心逻辑。当时我在简答题里把这套交互拆成状态机来描述从READY、DRAWING、DRAGGING、RESIZING几个状态间如何流转都画了出来这对阅卷人理解设计很有帮助。6.2 数据可视化前端技术栈里最能体现AI价值的方向数据可视化在AI公司前端工作中的核心地位从笔试题目上就能看出来。我记得有题目提到模型训练过程中的loss曲线实时展示问如何实现平滑更新与高性能渲染。这其实就是数据可视化中非常典型的场景。绘制loss曲线通常用折线图但数据量大的时候如果每秒更新几十个点并全部重新绘制性能很容易崩。我在回答里提到了两种手段一是对历史数据进行抽稀只保留关键点控制绘制点数在合理范围内二是用离屏Canvas预渲染静态背景动态部分只绘制增量区域减少不必要的重绘开销。如果你对ECharts、G2这类成熟库比较熟也可以提一下它们的底层逻辑和适用场景。但更有竞争力的回答是结合Canvas自研轻量级图表引擎的方案因为AI场景下的标注工具、数据看板往往要求定制能力很强通用图表库未必能直接满足需求。商汤笔试更想看到的是你具备从底层理解可视化实现原理的能力而不只是会调用上层API。6.3 前端在AI产品中的角色从“页面生产者”到“算法输出可视化者”做完整套笔试题后我对前端在AI公司的角色有了全新的理解。传统互联网前端是面向用户做交互体验而AI公司的前端服务对象常常是算法工程师、数据标注员或者需要直观理解模型效果的客户。你做的事情本质上是在“算法模型”和“人”之间搭建可视化、可交互的桥梁。这意味着你需要懂得一些基本概念什么是分类任务、检测模型的输出格式通常是什么样的、一个常见的标注工作流需要哪些步骤、模型推理出的结果如何在Web端展示和复核。笔试不可能把所有业务知识都考到但它会通过一两道业务逻辑题来判断你是否具备这些领域的敏感度。7. 备考路径与实战建议这套打法你可以直接用7.1 分阶段复习框架如果你正在准备AI类公司的前端校招我建议按四条线并行推进每条线侧重一个维度。第一线是JavaScript核心机制把原型链、闭包、事件循环、异步方案、this绑定这些点挨个啃透每学一个点都要找对应的综合题练手。第二线是前端工程化与框架原理不要停留在API调用建议打开Vue/React的源码或者核心设计文档弄懂响应式原理、diff算法、渲染过程这些底层逻辑。第三线是Canvas和可视化基础系统过一遍Canvas 2D API至少写一个带交互的绘图demo有条件的再接触一下WebGL。第四条线是算法与数据结构把LeetCode上数组、链表、二叉树、字符串、动态规划入门这几类题刷熟。时间分配上如果还有一个月左右我建议JavaScript和算法各占35%工程化占20%Canvas和可视化占10%。这个比例和笔试权重基本匹配。7.2 做题顺序与时间分配技巧笔试的时间管理非常关键。商汤第二场笔试题量大、题型杂如果在一道题上卡住后面的综合题可能来不及写。我的经验是先快速扫描全卷把题目按“有把握”和“需要思考”分类有把握的先做确保基础分拿到需要思考的暂时跳过最后集中火力攻克。代码题优先写可运行版本哪怕是暴力解法也可以不要因为追求最优解而迟迟不动键盘。有时间再优化时间复杂度和空间复杂度在注释里写明优化思路即可。对于简答题尽量用分点结构作答让阅卷人一眼看到你的逻辑层次。7.3 更多值得注意的细节笔试前我还建议做两件事一是把所有高频手写题整理成自己的题库防抖节流、深拷贝、Promise.all、事件总线、数组去重、call/apply/bind这类题做到能理解、会默写二是梳理一个自己的项目经历复盘不一定是AI相关项目但要用前端视角讲清楚技术方案选型、性能优化和踩坑过程这部分综合题里非常有用。到了笔试现场网络环境最好提前测试稳定答题环境如果是在线编辑器要提前熟悉它的语法提示机制。代码题提交前再确认一下语言版本避免出现使用某个API但目标环境不支持的尴尬情况。8. 避坑指南与复盘心得8.1 我踩过的典型误区先说一个我自己真实踩过的坑复习阶段过度聚焦框架和工具忽略了JavaScript底层细节。那一年我花了很多时间研究Vue组件通信、webpack插件配置却对事件循环的微任务时机、原型链查找规则这种基础考点放松了警惕。结果笔试遇到综合题发现基础不牢的时候临时补已经来不及了。第二个坑是算法题写得少。平时工作中很少需要手写链表反转导致笔试时思路清晰但代码细节错误频出。这次教训之后我养成了每周至少刷三至五道算法题的习惯不是为了刷题而刷题而是为了让代码手感保持在线状态。第三个坑是备考时忽略了AI公司的业务场景。我最初以为去商汤做前端核心能力要求还是标准前端技术栈结果发现Canvas绘制、数据可视化、图像标注交互这类场景是绕不开的主题。如果你目标明确就是AI公司这类知识一定要提前铺开哪怕不精通也要了解核心API和实现思路。8.2 综合题的答题结构与表达技巧商汤笔试的简答题和综合题回答结构直接影响得分。我习惯用三层结构组织答案先说结论再说原理最后给示例。举个例子题目问如何优化一个加载大量图片的标注页面我先写“核心思路是减少同时渲染的图片数量、降低单张图片的解析压力、以及合理调度渲染任务”然后分别解释懒加载、Canvas抽帧、虚拟滚动各自解决的问题最后给一个简单代码示例说明交互层如何配合。表达层面尽量使用专业但不过分堆砌术语的措辞。要在答案里体现出你对边界情况有意识比如提到“如果用户快速拖拽标注框需要做节流或requestAnimationFrame控制更新频率”“如果图片过大先做降采样再绘制预览图”这类细节会比泛泛而谈更有说服力。8.3 心态与体能管理笔试时长接近两个小时中间还有多道手写代码题对注意力和手速都是考验。建议提前调整作息不要熬夜头脑清醒比多刷一套题更重要。答题过程中遇到完全没思路的题不要慌先跳过性价比优先。全场笔试更像是一场限时的高强度工程实践本质上考验你在压力下的技术输出能力。9. 写在后面的一些个人体会回头看这场笔试它让我对前端这个岗位的认识发生了很大改变。以前我觉得前端就是把设计稿变成页面跟数据结构和算法关系不大更不用碰Canvas这种偏图形学的东西。真正做完商汤第二场笔试我才意识到技术栈只是表象一家公司对工程师的核心期待是你能够应对各种不确定的技术需求——今天写标注工具明天做可视化大屏后天优化一个WebGL渲染流程。备考期间我最受益的习惯是把每一道错题都写成一篇小的复盘笔记不仅记录正确答案还写清楚错误原因和对应的知识盲区。到笔试前一周这本笔记就成了我最高效的复习材料。如果你即将参加类似的前端校招笔试不管目标是AI公司还是其他类型的互联网公司我的建议都一样把JavaScript理解透把算法手感保持住把框架原理琢磨明白再去拓展一些有技术深度的领域。基础扎实之后无论卷子怎么出你都能找到解题的抓手。最后分享一个我后来面试时经常用的小技巧遇到任何一道题先在心里把题目拆成三个维度——这道题考的是什么知识点、它可能的应用场景是什么、如果我来设计这个功能我会怎么做。这套拆解习惯能让你在笔试和面试中都保持清晰的思路。