
我把自己过去一年半的经历盘了一遍结合最近这轮集中面试的实战遇到的问题整理了一份前端面经。这不是那种漫天撒网的八股文汇总而是从我自己真实经历出发梳理出的技能提升路径、面试答题思路以及踩过坑之后总结出的避雷清单。1. 为什么说一年半经验是面试市场里最尴尬的位置工作一年半左右的前端在招聘市场上其实处于一个非常微妙的位置说是新人你已经独立负责过模块说是资深你又还没经历过大型项目的完整架构演进。这个阶段去面试很多公司会拿高级前端的尺子来量你但给的预期又可能是中级偏上两边一拉扯对候选人来说非常容易受挫。1.1 一年半在招聘方眼里到底是什么水平我自己的体感是面试官看到一年半经验这几个字时心理预期基本是这条线——基础语法没问题但不会指望你能默写所有 API框架能熟练用但会追问“为什么这样写”而不是只满足于“能跑”项目讲得出细节但更在意你在项目里有没有解决过非教科书问题算法不会考 hard 题但手写一个防抖节流、数组去重、深拷贝这类基本功基本是标配对工程化、模块化、性能优化有一定的认知不需要精通但得说出个所以然。换句话说一年半经验对应的不是你会不会写代码而是你有没有形成自己的技术判断。很多面试题其实没有标准答案面试官想看的是你临场思考的路径而不是背好的结论。1.2 我决定系统性准备面试前先做了三件事我的第一轮面试其实很狼狈几乎是裸面。被问到很多感觉学过但说不透的知识点之后我给自己踩了刹车先做了三件事第一把过去一年半写过的代码拉出来按模块复盘找出哪些是自己真正踩过坑、有深度思考的哪些只是照着文档抄的。这个动作帮我确定了自己简历上最值得讲的素材。第二做了知识体系的分类。我把面试题粗略分成JavaScript 基础、浏览器与网络、框架原理、工程化、性能优化、手写题、软技能与项目深挖这七类。这一步不是为了刷题而是为了定位哪些部分有系统积累、哪些部分纯靠临时补。第三定了一个时间安排。白天上班晚上留出两小时固定复习周末集中做两次模拟面试。模拟面试不是自己问自己答而是找我一个朋友挑刺提问这个效果比刷题好很多。这个过程中我最大的感触是知识体系必须自己搭不能靠零散的面经拼凑不然一到追问环节就露馅。2. 简历投递先别急着写项目把能力证明链想清楚简历是面试的第一关但很多人包括我一开始都犯了一个错把所有做过的项目平铺直叙地列上去感觉像写操作手册。其实简历不是用来堆砌的它可以被理解为一条能力证明链你想证明自己会什么就用一个项目、一个场景、一个结果去对应它。2.1 一年半经验的项目描述最忌讳写成流水账我见过很多简历上的项目描述是这种风格负责了后台管理系统的开发使用 Vue 和 Element UI 实现页面和后端联调接口修复 bug。这种描述没有任何判断力面试官看完根本不知道你的水平在哪里。同样是这个项目更有价值的是突出问题-行动-结果的结构比如针对后台导出大数据量接口超时的问题采用前端分片请求懒加载方案将导出耗时从 30 秒降到 5 秒以内同时增加了进度反馈避免用户重复点击。这两段的差别在于后者能迅速让面试官锁定这个候选人遇到过性能问题、有解决方案意识、对用户体验有感知而这些问题恰好就是前端面试中最高频的追击点。所以写项目之前先把我做过哪些有挑战的事列出来再挑 2-3 个最有代表性的写进简历不要贪多。2.2 技术栈清单怎么列才不会被面试官追问到崩溃技术栈清单是一个大坑。很多人会把所有碰过的东西全部写上结果面试官挑了某个词一问自己当场答不上来白白浪费一轮。我的做法是把技术栈分成三档。第一档是精通级就是我日常工作最核心的技术能应对追问甚至能主动展开讲出底层实现的比如 Vue 3、TypeScript、Vite第二档是应用级熟悉基本用法能基于文档或项目经验解决问题但不承诺能讲清原理的比如 Webpack、Pinia、Axios第三档是了解级只在某些场景见过或自己做过简单的 Demo一般不主动往简历上写。简历上的技术栈尽量控制在第一档和第二档第三档写了就是在给自己埋雷。面试官会浏览他认识的每一个关键词这是一个很实际的避坑提示。2.3 投递节奏和岗位筛选思路投递这件事我的经验是不建议海投。海投之后很容易出现一天三四场面试的情况面到后面人已经麻木了状态和表达质量直线下降。我会把岗位分成三个梯队第一梯队是期望值很高但可能性偏低的第二梯队是匹配度不错、比较有希望的第三梯队是保底型的。面试顺序上可以先用第三梯队练手校准自己的表达方式和时间感等状态稳定了再集中面第二梯队最后再去冲第一梯队。这样做的好处是不会因为一开始被理想公司拒绝而心态崩掉也能在复盘中逐步优化自己的答题框架。3. 基础面试题的核心不是答案是演进逻辑一年半经验的面试基础题几乎是必经之路。但我在面试过程中发现一个很有意思的现象高频题还是那些问法却已经变了。以前是什么是闭包现在更常见的是闭包有没有内存问题、怎么排查、怎么优化。从知道到会用来解决问题就是一年半经验的分水岭。3.1 JavaScript 基础从执行机制到闭包面试官真正想听你怎么表达JavaScript 基础里最常被追问的几个模块无非是执行上下文与作用域链、闭包、原型链、事件循环、this 指向、ES6 新特性。比如问到事件循环重点不是背出宏任务微任务的定义而是能不能用一段代码推演执行顺序并解释为什么setTimeout的回调不一定在Promise.then之后。很多候选人会背结论但一被问到如果 setTimeout 延迟时间是 0为什么还是后执行就卡住了。其实这里要补的是setTimeout的延迟时间只是最小延迟它真正进入宏任务队列的时机还受主线程执行时间、微任务队列清空时机的影响。再比如闭包我会建议从作用域链保留的视角来讲配一个实际场景比如防抖函数、计数器、或者模块化时代前的 IIFE 模式。关键不是背定义而是让面试官知道你在真实开发里确实用过闭包并且理解它的内存代价。可以用一个例子function createCounter() { let count 0 return function () { count return count } } const counter createCounter() counter() // 1 counter() // 2然后顺势讲出count被内部函数引用形成闭包后不会被垃圾回收如果大量使用且不去解除引用可能造成内存泄漏。所以能用局部变量就不用闭包这个原则虽然听着简单但背后是内存管理的思考。3.2 浏览器与网络把页面加载过程讲成一个完整的故事浏览器和网络相关的问题如果只是背步骤很容易被追问到细节就卡住。我推荐把从输入 URL 到页面展示这个过程练成一个完整的故事先讲输入 URL 后浏览器做的第一件事是解析 URL、查缓存、DNS 解析然后建立 TCP 连接之后发 HTTP 请求服务器返回 HTML浏览器边解析边加载遇到 CSS 和 JS 会阻塞渲染最后生成 DOM 树、CSSOM 树合并成渲染树再进行布局和绘制。这个故事里几乎任何一个环节都能拿出来深挖。比如为什么建议把 script 标签放 body 末尾、CSS 会阻塞渲染吗、DOMContentLoaded 和 load 事件有什么区别、DNS 解析会缓存吗、HTTP/1.1 和 HTTP/2 在并发请求上有什么差别、强缓存和协商缓存的区别。这些都不是孤立的知识点而是连成一条链的。我在模拟面试的时候发现自己对渲染过程讲得特别浅只能说到生成 DOM 树、CSSOM 树这种程度。后来我专门练了分层渲染的概念浏览器把页面分成合成层和普通层某些 CSS 属性比如transform、opacity能触发 GPU 合成避免重排重绘这也就是为什么现代前端做动画都推荐用这些属性。讲到这里面试官通常会明显对你另眼相看因为这已经不是基础层面而是和性能优化接轨了。3.3 CSS 和布局问题背后的体系化思维CSS 问题在一年半经验面试中往往不是裸考选择器优先级而是结合布局场景来问。比如怎么实现一个左侧固定 200px、右侧自适应的两栏布局——这道题就有很多种方案flex、float、grid、定位、calc 都可以实现关键在于你要能说出每种方案的特点以及什么场景下选哪个。我的建议是把 CSS 问题往体系化方向整理盒模型、层叠上下文、BFC、flex 和 grid 的适用场景、移动端适配方案rem / vw / 媒体查询、position几种值的定位规则、以及z-index为什么有时候不生效通常都是层叠上下文的问题。如果每个点都能对应一个小案例就不怕被追问。比如z-index失效是一个很经典的案例。很多人只知道z-index越大越靠前但忽略了它只在同一个层叠上下文内比较。而position: relative加上一个z-index: 1或者transform、opacity小于 1、filter等属性都能创建新的层叠上下文。一旦父级创建了层叠上下文子元素的 z-index 就只在父级内部作比较了。这个点在面试中非常容易用案例题考察值得提前整理清楚。4. 框架源码题的高频覆盖区响应式、diff 与组件通信框架题对一年半经验的人说已经不是会不会用的层面而是你知不知道它底层干了什么的层面。我主要技术栈是 Vue但我也被问过 React 的一些核心概念比如虚拟 DOM 和 Hooks。所以这个阶段框架题的基础逻辑其实是相通的虚拟 DOM、diff 策略、组件通信、状态管理边界、渲染机制五大块值得重点攻克。4.1 Vue 和 React 的选择题与必问题先说 Vue 3 这边。几乎必问的是 Composition API 和 Options API 的对比、ref和reactive的区别、computed和watch的区别、生命周期钩子变化以及最重要也最容易被追问的响应式原理。Vue 3 的响应式是基于Proxy实现的这几乎是常识但面试官不会只停在这句话。他会接着问reactive返回的代理对象和原对象是什么关系为什么reactive只能用于对象不适用于原始类型ref为什么能处理原始类型ref在模板里为什么不用写.value而在 JS 里要写这些问题是把用过框架和理解框架区分开的关键。React 那边的高频题则包括Hooks 的依赖数组设计、useEffect和useLayoutEffect的区别、函数组件和类组件的差异、如何模拟shouldComponentUpdate、React 的 diff 算法如何从 O(n^3) 优化到 O(n)。如果你没有实际写过 React至少要把 diff 的核心思想理解到位同级比较、key 的作用、类型不同直接销毁重建、通过 key 来优化列表更新。这套逻辑和 Vue 的 diff 是相通的。4.2 组件通信一年半经验最容易被追问的场景组件通信这个考点表面上是考察知识面实际上是考察你在实际项目中拆分组件的思路。常见通信方式包括props 父传子、emit子传父、provide/inject、事件总线、v-model、以及状态管理工具Vuex / Pinia / Redux。我面试时被问过一道比较有代表性的题如果两个不相干的组件需要共享一个状态你会怎么做很多候选人第一反应是上 Vuex/Pinia但更合理的思路是先看共享状态的作用范围如果只是页面内两三个兄弟组件可以考虑provide/inject或者一个简单的 reactive 对象如果跨页面、需要持久化、有复杂的异步更新逻辑才需要引入状态管理库。这个问题背后的潜台词是你有没有技术选型边界的意识而不是所有场景一律上全家桶。4.3 状态管理的使用边界状态管理的边界问题一年半经验的人其实很容易犯错。项目里一开始很爽地用了 Pinia全局塞了一大堆状态结果后来发现改了state但没人知道从哪改的调试成本飙升。在面试里聊到状态管理时我会主动提这些边界和维护成本。比如业务组件内部状态优先用ref/computed自制跨层级组件通信优先考虑provide/inject真正需要多页面共享、异步更新、模块间强耦合的状态才进 Store。这样一段话会让面试官觉得你不仅会写代码还考虑过代码的长期可维护性这一点在一年半经验里很加分。5. 工程化、性能优化、手写题这三类题目决定了你能不能进下一轮除了框架和基础工程化和性能优化是检验前端有没有生产环境经验的试金石。而手写题则像一面镜子直接反映你的编码基本功。5.1 性能优化不能只背指标要能算账性能优化在面试里出现的频率非常高但很多人的回答都停留在图片懒加载、路由懒加载、CDN、打包压缩这种通用套话。面试官如果继续追问那你做过哪些优化优化前后有什么数据对比很多人就答不上来了。我的建议是从自己实际的项目中找出一个具体的性能问题把优化思路和结果写清楚。比如我之前遇到过列表页首屏渲染太慢的问题排查后发现是接口数据量太大、图片资源未压缩、页面同时加载了全量组件。我做的优化组合是路由层面做代码分割配合动态导入首屏只加载当前路由需要的 JS 包列表采用虚拟滚动只渲染可视区内的数据而不是一次渲染几百条 DOM图片统一走 CDN 并提供 WebP 格式配合loadinglazy属性做懒加载给请求加缓存策略接口数据在内存里做一层缓存避免重复请求。效果这一段也不要全口说最好能拿出数据比如首屏速度从 2.8 秒降到 1.2 秒包体从 800KB 降到 450KB。哪怕没有精确的数字用体感速度明显提升也比笼统说做了很多优化要好。5.2 工程质量前端工程化相关提问的答题结构工程化的提问方向很多比如 Webpack 和 Vite 的核心区别、ESM 和 CommonJS 的差异、怎么配环境变量、怎么做代码规范、CI/CD 流程里前端承担什么角色。如果准备不够充分这边很容易暴露短板。我比较推荐的方式是把工程化问题往三个维度归构建层、规范层、发布层。构建层聊打包工具的优化比如loader和plugin的区别、tree-shaking的条件、代码分割的策略规范层聊 ESLint / Prettier / husky 在提交前卡代码规范发布层聊 CI/CD 的流水线里前端怎么构建、怎么产出dist、怎么推到 CDN 或服务器上、怎么处理版本回滚。如果遇到一个不太了解的工程化概念不要直接说没接触过。可以先按我理解的它是用来解决什么问题来回答然后补充在我们项目中可能还没有特别深入地用到。这样既展示了理解能力也不会显得在不懂装懂。5.3 手写题的真实难度曲线一年半经验的手写题范围其实很固定防抖、节流、深拷贝、数组去重、手写 Promise、手写发布订阅、用 reduce 实现 map、手写一个简单的new等。难度不会太高但要求写出的代码能跑、边界情况能覆盖。以深拷贝为例很多人的答案会写成function deepClone(obj) { return JSON.parse(JSON.stringify(obj)) }这能得基础分但面试官一般会追问如果对象里有Date、RegExp、undefined、函数、循环引用你这个方案会出什么问题所以更好的做法是手写一个递归版深拷贝并处理几种常见类型function deepClone(obj, map new WeakMap()) { if (typeof obj ! object || obj null) return obj if (obj instanceof Date) return new Date(obj) if (obj instanceof RegExp) return new RegExp(obj) if (map.has(obj)) return map.get(obj) const clone Array.isArray(obj) ? [] : {} map.set(obj, clone) for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { clone[key] deepClone(obj[key], map) } } return clone }用WeakMap是为了应对循环引用避免递归死循环。这段代码能写出来面试官对基础能力的信任度会提高不少。而防抖节流这类题目重点是要说清楚应用场景防抖适合搜索框输入、窗口 resize 这种连续触发但只需要最后一次的场景节流适合滚动、拖拽、频繁点击这种需要控制执行频率的场景。6. 微前端、AI 开发工具与新趋势题怎么答这两年面试趋势题变化非常明显。以前可能问你对 Vue3 怎么看现在会问你用过微前端吗你怎么看待微前端在项目里的价值你平时用 AI 工具吗它对你的开发效率有什么影响这类题目没有标准答案但考察的是候选人对行业动向的敏感度和思考深度。6.1 微前端被问到时怎么组织答案微前端这个方向很多同学会担心没做过微前端项目就答不了。其实微前端问题的核心不是你有没有用过某个具体框架而是你有没有理解它解决的痛点。我会这样组织答案先讲背景当一个项目体量变大后团队拆分、技术栈统一、独立部署都变成难题。微前端的价值也不是技术上的炫技而是让多个团队可以独立开发、独立部署、独立上线同时又能组合成一个完整产品。再讲实现思路微前端的关键是主应用 子应用的加载机制。常见方案包括 iframe、Web Components、JavaScript 运行时共享以及比较流行的qiankun、micro-app之类的框架。不管你用没用过至少要理解它们是靠在主应用里注册子应用、动态加载子应用的入口 JS、把 HTML 挂载到指定节点这种方式工作。最后补一点风险意识微前端不是银弹它也有它的问题比如子应用之间样式隔离、状态共享的复杂度、首屏性能损耗、通信机制的设计。面试时如果能把值不值得用的判断逻辑说出来会比你单纯背书更有说服力。6.2 AI 工具相关提问背后的潜台词这一题在最近的热搜里也很突出。面试官问你平时用什么 AI 工具时其实并不想听你列一堆工具名真正想了解的是你有没有把它纳入日常工作流、能不能判断 AI 生成代码的质量、以及在 AI 提示词不给力时能不能自己兜住。我自己的回答思路是先说自己常用的是哪些工具比如 GitHub Copilot 或各类在线 AI 辅助编程插件再讲一个真实的使用案例比如在写一些重复性高的组件模板时我会让 AI 先生成初版我再手工调整类型和边界情况重点说明AI 可以加速编码但代码 review 和边界判断仍然得我自己来。如果能再提一句我会要求 AI 不要写多余代码生成的代码我会做逐行确认会显得更有工程素养。6.3 如何应对你不会的题面试中一定会遇到自己不会的题。我曾经被问到一个非常冷门的问题当场大脑空白。后来我总结出一个比较安全的答题流程先复述一遍题目确认自己理解对了然后说这块我没有深入实践过但根据我对 XX 的理解它大概是在解决 XX 问题。这样做是为了展示你具备迁移理解的能力。如果完全不知道也要勇敢说这个我确实还没遇到过能跟您请教一下吗不建议瞎编。大部分面试官都很愿意解释而且你诚实的反应反而会留下好印象。7. 我的面经复盘两次求职周期的对比、得失和最后建议这轮面试走下来让我比较明显地感觉到了一年半经验这个阶段和刚毕业时的区别刚毕业时面试问的是你会什么一年半之后再面问的是你在项目里做过什么、怎么做的、为什么这么做。整个逻辑从知识点记忆转向了经验价值输出。7.1 第一次仓促面试的教训我最早投简历的时候没有做知识体系和面试模拟直接裸面了两家。结果非常惨烈被问到Vue 3 的响应式原理我只说出用的 Proxy被追问Proxy 和 Object.defineProperty 有什么区别当场卡住被问到项目中最有挑战的点我讲得毫无主线手写一个防抖函数写出来后忘了处理 this 指向。这次经历让我很清楚面经不是背诵材料它只是帮你找到盲区的工具。真正值钱的是你自己建起来的技术故事的骨架。之后我花了大约两周时间一个模块一个模块地补齐盲区再进入第二轮投递。7.2 框架化表达方法到了第二轮我明显感觉回答问题更稳了。核心方法是我自己总结的框架化表达任何一个技术问题先给出结论再展开原理最后结合场景收尾。给你举个例子。当面试官问Vue 的 computed 和 watch 有什么区别时我第一轮可能直接开始背computed 是计算属性watch 是监听器……”这样虽然是对的但缺乏组织。第二轮我会这么答先说本质computed是根据已有响应式数据派生出新值的它关注的是计算watch是为了在响应式数据变化时执行副作用逻辑它关注的是过程。再展开原理computed有缓存机制依赖不变不会重新计算watch没有缓存数据一变就会执行回调。最后落到场景如果我要根据输入框的值实时计算一个总价用 computed如果我要监听路由变化来上报埋点用 watch。这个答题结构的好处是让面试官在很短的时间内抓到你的骨架。我后面几乎对每个高频问题都用这样的方式重新整理过自信心一下就上来了。7.3 我最后留下的几个建议第一个建议花时间建立自己的知识树不要只刷题。面试题是树叶知识体系是树干两者需要同时存在。只刷树叶一被追问就散架只建树干一到手写题就露怯。第二个建议项目复盘比面经更重要。把你做过的事当做一个真实项目去拆解遇到了什么问题、为什么这么解决、有没有更好的方案、数据效果如何。这个过程不需要多么高大上的项目一个普通的后台管理系统也能讲出深度。第三个建议模拟面试非常值得做。我在备面过程中会定期找朋友做一对一的问答模拟每次 40 分钟结束之后复盘录音。这个方法有奇效因为它能帮你发现自己以为会了但实际表达不清的知识点而这些模糊地带往往就是面试被淘汰的暗坑。最后一个建议保持不过度练习的松弛感。面试本质上是一次双向沟通不是考试。保持适度的紧张就好过度紧张容易导致回答语速过快、失去节奏。我自己第二轮面试后期基本就是抱着聊项目的心态去的反而发挥更自然面试官也更愿意深入交流。这条心得未必适用于所有人但如果你也属于那种容易紧张的类型值得试试。