奇安信前端笔试题复盘:深拷贝、事件循环与XSS防御等硬核考点解析

发布时间:2026/8/29 22:20:10
奇安信前端笔试题复盘:深拷贝、事件循环与XSS防御等硬核考点解析 2019年春天我拿到了奇安信的前端开发笔试题当时的第一反应是这家公司考的怎么这么“硬核”。别的公司还在问Vue生命周期和flex布局它已经把手写深拷贝、事件循环输出题、XSS防御方案、甚至webpack的plugin机制全部塞进了一张卷子里。做完之后我复盘了很久后来这些年也陆续帮朋友看过不少大厂前端笔试题回过头再翻开这份试卷很多东西依然有参考价值。这篇文章我会以“过来人”的视角把奇安信2019春招前端开发试题里最典型的几类考点拆开讲清楚为什么考、怎么答才拿分、有什么容易踩的坑。无论你是准备面试的候选人还是负责招聘出题的同行抑或是想夯实基础的中级前端这篇内容应该都能给你一些启发。1. 试题整体设计与考察思路1.1 从题型分布看考察方向奇安信2019年春招前端试题的题型整体可以划分为四类选择题与填空题、手写代码题、简答题、综合场景设计题。其中选择题覆盖很广从HTML语义化标签到TCP三次握手都有涉及但难度不算深主要用来筛掉基础不牢的人。真正拉开差距的是手写代码题和简答题。那年的笔试题里手写防抖节流几乎是必考项深拷贝也出现了。这类题不是让你默写而是看你面对边界条件时能不能想到、能不能处理干净。我印象里有一道题是问“深拷贝时遇到循环引用会怎样”很多同学答“会栈溢出”但只有少数人能写出用WeakMap解决循环引用的方案。这种细节就是阅卷时的分水岭。1.2 为什么奇安信的题比一般公司“硬”奇安信不是普通互联网公司它的核心业务是政企安全、数据安全、安全运营平台。这意味着两件事第一前端工程师要做大量复杂的管理后台、可视化大屏、数据报表所以对JavaScript性能和渲染性能有要求第二作为安全公司它对Web安全的理解必须刻进每个岗位的骨子里包括前端。这一点直接反映在试题里比如有一道简答题是关于XSS的防御方案还出现了“输入校验与路径遍历”这类带有安全色彩的考点。普通公司可能把Web安全放在加分题里奇安信直接把它放在必答题里。我当时做完就有一种感觉这不是单纯招前端而是在招“懂安全的前端”。所以如果你准备投这类安全公司web安全基础、前端安全编码习惯一定不能裸考。2. 核心考点拆解JavaScript基础与进阶2.1 原型链与this指向问题原型链和this指向在2019年的前端面试里属于“保留曲目”奇安信也不例外。它出现在一道选择题里给出一段代码让选出输出结果代码大概长这样function Foo() { this.value 1; } Foo.prototype.getValue function() { return this.value; }; const foo new Foo(); const getValue foo.getValue; console.log(getValue());这题的核心考点有两个第一this的绑定规则——getValue是作为普通函数调用的此时this指向window或undefined取决于是否为严格模式而不是foo第二Foo.prototype上的方法本质上就是普通函数它的this不天然绑定到实例上。答题时建议按“四步走”思路先判断调用方式再套绑定规则然后考虑严格模式影响最后确认输出。很多人在这题上栽跟头是因为把“方法定义在原型上”和“方法调用时绑定this”两件事混淆了。我自己的经验是做这种题不要背结论要练习用规则推导。2.2 事件循环与异步编程顺序异步编程的考察主要是让你预测一组setTimeout、Promise、async/await的输出顺序。比如console.log(1); setTimeout(() console.log(2), 0); Promise.resolve().then(() console.log(3)); async function test() { console.log(4); await Promise.resolve(); console.log(5); } test(); console.log(6);大部分人会答成“1、4、6、2、3、5”而正确顺序是“1、4、6、3、5、2”。这里的关键在于await后面跟着的Promise.resolve()会生成微任务但await本身会立即让出执行权所以后面的console.log(5)是等微任务执行完才运行的而微任务又优先于宏任务。这个考点考察的其实不是背结论而是对事件循环机制的理解。如果要展开讲宏任务和微任务的执行规则可以画成一句话每执行完一个宏任务都会清空整个微任务队列再进入下一个宏任务。答题时如果能顺带提一句Node.js和浏览器在事件循环实现上的差异那会是一个不错的加分点。2.3 手写代码题防抖、节流、深拷贝、Promise.all手写题是奇安信笔试的“重头戏”。当年比较常见的是防抖和节流现在几乎已经是前端面试的标配了但放在2019年能写得干净利落的人比例并不高。防抖的核心是设置一个定时器在连续触发时重置时间保证最后一次触发后等待一段时间才执行function debounce(fn, delay 300) { let timer null; return function (...args) { if (timer) clearTimeout(timer); timer setTimeout(() { fn.apply(this, args); }, delay); }; }节流的常见实现是时间戳版本或定时器版本。我在答题时一般写定时器版本因为它更好理解function throttle(fn, interval 300) { let timer null; return function (...args) { if (timer) return; timer setTimeout(() { fn.apply(this, args); timer null; }, interval); }; }这里容易忽略的点有两个一是this的透传用了apply才能让原函数在正确的上下文里执行二是防抖和节流的使用场景面试官很可能追问“什么时候用防抖什么时候用节流”我的习惯是答“输入框实时搜索、按钮重复提交用防抖滚动监听、拖拽、resize用节流”。深拷贝这个题也是必背内容但真正高分答案要处理这些边界Date、RegExp、Symbol、函数、循环引用。function deepClone(obj, hash new WeakMap()) { if (obj null || typeof obj ! object) return obj; if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags); if (hash.has(obj)) return hash.get(obj); const clone Array.isArray(obj) ? [] : {}; hash.set(obj, clone); for (const key of Object.keys(obj)) { clone[key] deepClone(obj[key], hash); } return clone; }注意这里用了WeakMap而不是Map因为WeakMap的键是弱引用不会造成内存泄漏。循环引用是关键场景var a {}; a.self a;如果不做缓存处理递归会无限循环导致栈溢出。这个边界条件2019年的考卷上如果写出来了基本就是满分思路。3. 浏览器端必考渲染机制与性能优化3.1 从输入URL到页面展示的完整链路奇安信的前端考题里有一类“串链路”题让你描述从输入URL到页面展示的完整过程。这种题考察的是知识树的完整性DNS解析、HTTP请求建立、服务器响应、浏览器解析渲染每一步都可以深挖。我当时回答时把过程分成四段DNS解析域名拿到IP通过TCP三次握手建立连接如果是HTTPS还要加上TLS握手协商密钥浏览器发起HTTP请求服务器返回HTML、CSS、JavaScript浏览器解析HTML构建DOM树解析CSS构建CSSOM树两者合成渲染树经过布局和绘制后呈现在页面上。如果页面里有图片、JavaScript还要考虑并发加载和阻塞解析的问题。答题时有个加分细节渲染过程中script标签会阻塞DOM解析所以需要把脚本放在/body前或者加defer/async属性。这个点看似基础但结合后面的性能优化题来回答就能让阅卷人看出你理解的是“为什么”而不是“背答案”。3.2 回流、重绘与合成奇安信考题中关于性能的题目很多会落到“回流reflow与重绘repaint”上。比如有一道题问为什么用transform做动画比修改top/left性能好答案不只是“transform不会触发回流”更准确的说法是transform会触发合成层动画过程在合成线程完成不涉及主线程的布局和绘制。答题时我建议把浏览器渲染管线列出来DOM树构建 → 样式计算Style → 布局Layout → 绘制Paint → 合成Composite。如果修改left会触发 Layout 和 Paint后续每一步都要重新执行如果修改transform只是改变合成层的位置Paint 和 Layout 都能跳过所以更流畅。为了体现深度可以补一句减少回流还可以通过批量修改样式、使用documentFragment或先把元素设为display: none再进行DOM操作。这些技巧本身就是性能优化题的答案素材。3.3 线上数据大屏的性能优化切入点结合奇安信的业务场景数据可视化大屏很可能是日常开发中绕不开的模块。我在实际做这类项目时有一个体会大量图表同时渲染时性能瓶颈往往不在绘图本身而在数据的处理和DOM的更新方式。常用的优化策略包括图表按需渲染而不是一次性渲染全部把图表实例的setOption操作合并减少不必要的重绘利用requestAnimationFrame控制更新频率大数据量时用canvas而不是svg。答题时如果能把性能和业务场景结合起来比如“安全运营中心的告警大屏如果有上万条告警同时滚动更新应该怎么做优化”那就能体现出你在真实项目中思考过而不是只会背概念。4. 前端安全方向安全公司的独特考察点4.1 XSS的类型与防御措施奇安信作为安全公司前端试题里出现XSS太正常了。这类题通常会让描述XSS的分类以及各自的防御方案。XSS包含三大类存储型、反射型、DOM型。区分它们的关键是恶意脚本的来源和注入位置存储型和反射型都是服务端漏洞只是存储型是持久化的反射型是拼接在URL参数里的DOM型则是前端JavaScript直接操作DOM时造成的。防御措施要从多个层面作答。输出编码是第一步对不同上下文HTML标签、属性、JavaScript、CSS做对应编码使用CSP内容安全策略限制脚本来源设置HttpOnly防止Cookie被脚本窃取。我当年吃到亏的一点是只回答了“过滤输入和转义输出”忽略了CSP。阅卷人如果说“仅靠过滤是不够的”那其实是在提示你XSS的防御必须站在纵深防御的角度不能靠单一的防护手段这个思路是答安全题的底层逻辑。4.2 CSRF的攻击流程与token机制CSRF跨站请求伪造也是安全题的常客。理解CSRF的前提是明白浏览器的一个行为只要Cookie没过期请求会自动带上它。所以攻击者可以构造一个看似合法的请求诱导用户在不知情的情况下提交到目标站点。防御手段中的核心是CSRF Token机制服务端在页面渲染时生成一个随机token前端发起请求时带上这个token服务端校验。需要注意的是现在很多项目也依赖SameSiteCookie 属性来缓解CSRF比如配置SameSiteLax但我会建议在答题时说明它的限制——有些跨站场景依然无法完全覆盖。奇安信的题中如果出现CSRF很可能还会追问“前端在CSRF防御中能做什么”。常规答案是在请求头中手动加入自定义字段服务端校验该字段因为浏览器跨域时带自定义header会触发预检请求攻击者无法在不经过预检的情况下成功发起恶意请求。4.3 输入校验与路径遍历的隐患热词列表里有“输入验证路径遍历”这样的关键词说明当年的试题甚至包含了一些偏后端的安全概念。路径遍历Path Traversal是指攻击者通过构造包含../的路径来访问服务器上的任意文件比如../../../etc/passwd。虽然这是偏后端的漏洞但前端也可能参与其中。如果前端允许用户上传文件或输入文件路径并且直接传给后端处理就要考虑路径规范化的问题。答题时可以提到前端要对用户输入做白名单校验禁止包含../或绝对路径等危险信息更重要的后端必须做最终的路径规范化不能被前端的校验替代。这一题给我们的启示是安全公司的前端面试会考察你是否具备“安全开发”的全局视角而不仅仅是页面写得好不好。5. 框架与工程化Vue 2与webpack5.1 Vue 2响应式原理与虚拟DOM2019年Vue 2还是绝对主流奇安信的试题里也考了Vue 2的响应式原理。核心考察点是Object.defineProperty如何使用以及它的两个短板无法监听数组的变化需要通过重写数组方法解决、无法监听对象属性的新增和删除需要使用Vue.set和Vue.delete。答题时建议按“数据劫持 → 依赖收集 → 派发更新”的逻辑讲组件渲染时每个数据对象的属性都有对应的Dep组件渲染会触发属性的getter把 Watcher 收集起来数据变化时触发setter通知所有依赖它的 Watcher 更新。虚拟DOM的价值在于数据变化后不直接操作真实DOM而是通过 diff 计算出真正需要修改的部分。如果面试官追问 key 的作用可以这样答key 主要用来标识节点身份帮助 diff 算法判断节点是复用还是重建。列表顺序变化时如果没有唯一keydiff 会认为节点类型没变但内容变了会执行很多无谓的更新加上 key 之后Vue 可以精确地移动或复用节点。5.2 webpack loader与plugin的区别工程化方向奇安信2019年的试题里出现过“loader和plugin的区别”这种基础概念题。loader是文件转换器比如把 ES6 转成 ES5把 Vue 单文件组件转成 JavaScript 模块plugin则是在webpack整个构建过程的特定时机执行扩展逻辑比如HtmlWebpackPlugin会在输出阶段自动生成HTML文件。回答这个问题可以举一个落地的例子项目里需要把资源路径加上CDN前缀这个时候用output.publicPath配置即可但如果我们还想在构建完成后把多余的文件清理掉就需要CleanWebpackPlugin这种plugin来处理整个输出流程。整理成一句话loader作用在“文件”级别plugin作用在“流程”级别。构建优化方面当年比较常用的是happypack或thread-loader做多线程打包、DllPlugin预编译公共库、purgecss做无用CSS清理。现在webpack版本已经迭代很多次但这些思路依然有效——优化的本质无非是缓存、并发、按需引入、减少搜索范围这几类。5.3 前端工程化代码规范与项目骨架奇安信的业务大多涉及政企客户代码质量要求会比一般To C公司更高。这在试题中也隐约体现出来会有简答题问“你们项目的代码规范是怎么落地的”或者“Vue项目如何组织目录结构更利于维护”。这个问题没有标准答案但答题时要能说出具体的工具链和执行流程。比如用 ESLint Prettier husky lint-staged 的组合在 commit 前自动对暂存区的代码做校验和格式化能有效保证多人协作时风格统一。再比如目录结构上按模块划分业务代码把公共组件、页面、状态管理、工具函数分开同时通过别名避免深层相对路径的混乱。真实项目中这些工具组合的落地并不简单。ESLint 和 Prettier 的规则如果不提前统一会出现冲突husky 安装后需要配置 Hooks 路径lint-staged 如果配置过滤条件写错可能直接把所有文件都跑一遍。这些细节在作答时提一下会让面试官觉得你不是只会写demo。6. 常见问题与答题技巧实录6.1 答题顺序与时间分配策略奇安信2019春招的笔试题量不小我记得现场做题的时候时间是比较紧的。我的经验是先快速浏览所有题目优先做“一眼就知道答案”的选择题和填空题把该拿的分先拿稳然后做手写代码题这类题分值高即使写不全也能拿步骤分最后再做简答题和场景设计题。有些同学容易在简答题上花太多时间试图把每个概念都写得非常完美结果后面的手写题没有时间做。手写题的分数权重通常更高写出一版可运行的防抖函数比把XSS原理写三段更有用。所以如果时间不够简答题可以答要点、列出关键词不要纠结措辞。6.2 笔试中常见的丢分点复盘从我自己和后来帮同学复盘的情况看丢分点主要集中在几个地方。手写防抖节流时忘记处理this和args导致原函数在错误上下文执行深拷贝只处理普通对象和数组没考虑循环引用直接栈溢出事件循环输出题没有区分微任务和宏任务尤其是await后面的代码执行时机Vue响应式题目用了新术语“Proxy”解释但对 Object.defineProperty 的局限说得不够清楚webpack题把loader和plugin混为一谈这在阅卷时是非常明确的扣分点。丢分并不可怕可怕的是不知道自己丢在哪。我一般建议候选人这样自查做完笔试题后不要急着交卷把每道题的答案在脑子里过一遍如果是代码题试着把变量名、边界条件重新读一遍很多低级错误能在这一步被发现。6.3 面试现场追问与沟通技巧笔试题只是第一关后面的技术面通常会围绕笔试内容展开追问。我就遇到过这样的情况笔试写了防抖函数面试官追问“如果我想让节流第一次触发时立即执行应该怎么写”这实际上是在考你对节流背后的开关机制是否理解而不是只看你是否背出了代码。我的建议是面试时不要背诵答案而是用“问题拆解”的方式回答。先说思路再讲实现最后补充边界条件的处理。哪怕某个知识点记不全也可以说“我记得大致原理是XX但具体API我有些记不清了能不能让我再想想”。坦诚比假装自信更受认可尤其是在技术面试这个场景下。奇安信这类安全公司的面试官通常比较看重候选人的“安全感”。所谓“安全感”就是回答问题的时候你让面试官觉得你的知识边界是清晰的哪些是你确定的哪些你了解过但没用过哪些完全不会你能说清楚。这一点往往比一道题的答案完整还要加分。6.4 综合场景题安全信息系统的前端架构奇安信的试题里还有一种让我印象深刻的场景题假设我们要做一个安全运营中心的管理系统模块包括告警列表、用户权限管理、大屏展示、报表导出请描述前端的整体架构方案。这种题没有标准答案但考核点非常明确——有没有全局思维。我当时是分四个维度回答的工程层面使用Vue全家桶按业务模块划分路由和store组件库用ElementUI做二次封装权限层面前端路由守卫加动态路由结合用户角色配置菜单和操作按钮后端接口同样校验权限数据层面列表数据使用分页和懒加载大屏数据通过WebSocket推送增量更新报表下载用Blob处理流文件安全层面对导出接口返回的数据做校验防止越权导出前端对用户的输入做白名单管控并对富文本内容做XSS转义。这种回答的价值在于它让面试官看到你能把一个复杂系统拆解成可落地的执行方案而不是只会写局部代码。后来我做技术评审和招聘时也会用这道题来考察候选人的系统设计能力。个人经验收尾回头再看奇安信2019春招这套题它其实代表了一类“技术向业务向”结合的出题风格基础题考功底原理题考深度安全题考行业理解场景题考全局视野。它不简单但也是真的能筛出人。我在实际工作中最大的体会是面试题里那些花里胡哨的知识点最后都会落在日常开发的琐碎里。比如你理解了深拷贝的循环引用就会在写缓存工具时想到WeakMap你理解事件循环就不会再把所有异步问题都用setTimeout糊弄过去你理解XSS的深层原理就不会随便在业务代码里拼HTML字符串。所以我的建议很简单不管是准备面试还是日常提升别把时间都花在刷“题目印象”上。把奇安信这套试题当作一个知识体检单逐项检查自己哪些是真懂、哪些只是听说过然后回到原理层面补课。基础这层护城河挖得越深越不会被替代。

相关新闻