尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

前端实习面试全记录:从基础手写到项目深挖的实战复盘

前端实习面试全记录:从基础手写到项目深挖的实战复盘 1. 开年第四份面经是怎么来的投递节奏与岗位观察从大年初七开始改简历到二月中旬面完这家前前后后已经面了四家。前两场属于试水基本是裸考状态被面试官按在地上摩擦第三场慢慢找回节奏第四场也就是这家公司才算打出了一些正经操作。这份面经记录的是从投递到三面结束的完整过程包括每一轮被问到的问题、我当时的回答思路、以及事后复盘发现的准备盲区。先说投递节奏。春节后到三月中旬这个窗口是前端开发实习生岗位放出来最密集的阶段。大厂春招补录、中厂日常实习、还有一堆创业公司都在抢人但竞争体量同样吓人。我个人的策略是不海投只投那些JD里技术栈和我实际做过的东西重合度超过七成的岗位。与其投二十份简历等两三个面试不如精挑八家打底每场面试都能带着明确的复习方向去。这家公司吸引我的原因比较直接JD里明确写了负责中后台产品的前端开发技术栈以 Vue 3 TypeScript 为主还提到了组件库二次封装的需求和我之前课设、实习里做过的事情几乎一一对应。投完简历大概三天后收到的面试邀约HR电话里先聊了十来分钟问了些能不能实习、每周出勤几天、能实习多久这类基础问题。之后约了技术一面的时间在视频面试平台上面全程一个半小时左右节奏挺密集。整体感受是面试官不太关心你背了多少面试题而是很在意你说出来的东西有没有真实的落地场景支撑。这种面法对简历里有真项目的同学友好但对于靠突击刷题撑场面的同学会比较难受。配套关注的热搜词里前端开发面试题和前端开发skills这两个话题流量一直很高但我个人建议少看那种“百题斩”式的汇总。面试官也是从那个阶段过来的你答得像背题还是像用过几句话就能区分开。这个岗位明确要求“能快速上手业务开发”所以面试里所有题目都长在真实业务场景里几乎没有一道是纯八股。2. 面试前的技能盘点我拿什么去打这一场在投这家之前我花了一个周末把自己的前端技能树做了个彻底盘点。不是为了简历好看而是为了面试时被问到自己不熟的东西能第一时间判断该往哪个方向补。这里按我准备时的优先级列一下方便对标的同学参考。2.1 JavaScript 基础闭包、this 指向、事件循环、...arg 这类写法必须张嘴就来JavaScript 是前端开发的绝对地基说实话这是我最担心的一环。之前几次面试里被问到底层的时候就卡壳因为平时写代码用框架写多了很多基础概念停留在“看着认识”的水平。这次准备我给自己定了一个硬指标凡是面试题里高频出现的基础概念不仅要能说出定义还要能现场写出最小示例来解释。重点复习了函数声明与函数表达式在变量提升上的区别、闭包在循环事件绑定里的经典坑、以及剩余参数和展开运算符的使用边界。这里提一下...arg这个热词它其实是剩余参数和展开运算符的组合场景。比如这类题目function collect(a, b, ...arg) { console.log(arg); // 剩余参数收集多余的实参 } collect(1, 2, 3, 4, 5); // [3, 4, 5] const arr [1, 2, 3]; console.log(Math.max(...arr)); // 展开运算符面试官一般会接着问arguments对象和剩余参数的区别arguments是类数组没有数组的方法而剩余参数是真正的数组箭头函数没有自己的arguments但如果配合剩余参数就可以正常工作。还有一个变体是“手写一个函数参数个数不固定返回所有数字参数之和”这个时候用reduce配合剩余参数就是标准答案。事件循环这块我也花了不少时间。宏任务和微任务的执行顺序、async/await在事件循环里的特殊表现、setTimeout延迟时间的准确性这些不是光背结论就行得能画出完整的执行顺序。我找了好几个经典输出题自己先做一遍再看解析直到完全不出错。回头看这步准备很值得因为面试时那道事件循环题我只是回答了输出顺序还不够面试官还让我现场改了代码里的异步逻辑把它从串行改成并行。2.2 Vue 框架从模板语法到源码原理再到项目规范这次面试的技术栈核心很明确Vue。所以我在 Vue 上花的复习时间也是最长的。从使用层面我过了一遍 Vue 3 组合式 API 的常用写法ref、reactive、computed、watch、onMounted、defineProps、defineEmits这些基本API的用法和适用场景。这里有个心得不要只背API签名最好能说出来在什么业务场景下该用哪一个。比如watch和computed的区别表面上看是缓存问题但实际上背后是“声明派生状态”和“执行副作用”两种思维的差异面试官问这个问题时想听到的也是这一层。源码层面我重点看了 Vue 3 的响应式原理。基于Proxy的响应式实现和 Vue 2 基于Object.defineProperty的实现有什么区别、为什么 Vue 3 能监听新增属性和数组索引变化、ref和reactive在响应式实现上的差异、toRefs解构后为什么还能保持响应式。这些东西光靠看文档记不住我直接去 GitHub 上翻了一部分vue/reactivity的源码配合网上一些源码解析文章把整体流程过了一遍。虽然没法做到每个细节都记住但至少能解释清楚依赖收集和触发更新的基本过程。关于“前端开发规范vue”这个热词我也认真看了一眼。其实就是公司规范里常见的那一整套约定目录结构按模块划分、组件命名用 PascalCase、变量命名用 camelCase、样式使用 scoped 防止污染、提交信息按 conventional commits 规范写。面试官确实问到了项目里怎么保证代码规范我当时就说了自己参与的项目里的实践ESLint 规则配了plugin:vue/vue3-recommended提交前跑 lint-staged组件抽离按照页面区块划分而不是按功能堆料。这些听起来比“我们项目用了 ESLint”更有说服力。2.3 工程化、网络与浏览器被低估的隐藏考点除了 JavaScript 和 Vue我还复习了一轮前端工程化和网络基础。这几块在实习岗面试里占比不高但一旦问到就是送命题因为很多人会直接忽略。我当时准备的重点是Webpack 和 Vite 的核心差异、模块热更新的基本原理、HTTP 缓存的两类实现方式强缓存和协商缓存、从 URL 输入到页面渲染的完整过程、以及跨域的几种常见解决方案。网络层我复习了前端开发面试题里比较常见的几个TCP 为什么要三次握手而不是两次、HTTP 和 HTTPS 的区别、HTTP/1.1 和 HTTP/2 在并发请求上的差异、GET 和 POST 的语义区别。这些题目我给自己定的标准是能用自己的话讲清楚不用背教材原话。另外浏览器渲染流程也被问到了关键点在于解析 HTML 构建 DOM 树、解析 CSS 构建 CSSOM、合成渲染树、计算布局、绘制、合成。面试官很喜欢追问“JavaScript 放在 body 底部的原因是什么”以及“defer和async的区别”这两个问题其实是在考你有没有真正理解渲染流程和脚本阻塞的关系。3. 面试现场全记录每一轮被问到的问题和回答思路这家公司的面试流程是三面一面技术基础面、二面项目深挖面、三面综合面。整体节奏比较紧凑一面结束后两天内就安排了二面二面之后第三天是终面。下面是每一轮的详细记录。3.1 技术基础面从闭包到手写防抖考的是“熟练度”技术基础面是约的晚上七点视频面试面试官是一个看起来跟我年纪差不多大的前端工程师。开场几句自我介绍之后直接进入正题几乎没有寒暄。第一个问题就让我有点意外他让我说说“闭包是什么实际工作里哪些地方用到过”。我快速组织了一下语言先给了一个简单的定义然后补了一个实际的例子事件绑定时用闭包保存索引或者防抖函数内部用闭包保存定时器 ID。同时还提了一句“闭包会导致变量无法被垃圾回收所以不能滥用”这个隐患点。他顺着这个话题往下问了防抖和节流的区别并且要求现场手写一个防抖函数。手写的代码大概是这个样子function debounce(fn, delay 300) { let timer null; return function (...args) { if (timer) clearTimeout(timer); timer setTimeout(() { fn.apply(this, args); }, delay); }; }写完之后他追问了两个点第一为什么这里要用fn.apply(this, args)而不是直接fn(args)第二如果我给一个按钮绑定了这个防抖函数第一次点击是立即执行还是等 300ms 后才执行。第二个问题其实是考察“是否支持立即执行”这个边界情况我当时说默认是延迟执行如果需要第一次立即执行就得额外加一个immediate参数。根据我后来的复盘这地方如果能直接把带immediate参数的完整写法写出来会更有加分效果。之后又问了事件循环的输出顺序题。他的题目是这样的console.log(start); setTimeout(() { console.log(timeout); }, 0); Promise.resolve().then(() { console.log(promise); }); async function asyncFn() { console.log(async start); await 1; console.log(async end); } asyncFn(); console.log(end);我的回答是start、async start、end、promise、async end、timeout。讲一下关键理由asyncFn内部同步代码先执行await 1会把它后面的代码放到微任务队列微任务整体优先于宏任务所以在执行setTimeout回调前会先把两个微任务都执行完。注意顺序是promise在前、async end在后这是因为Promise.resolve().then先进入微任务队列。这轮最想提醒大家的是手写题不是写出来就完事了面试官一定会追问边界条件。写完防抖之后他还问了“如果用户快速点击一万次会执行几次”目的是考察对防抖原理的理解是否真实。所以复习时不要只背代码模板要把代码中每一行为什么这么写搞明白。3.2 项目深挖面简历上每个字都要经得起追问二面是项目深挖面面试官是部门的技术负责人。这一轮没有直接问知识点而是盯着我简历上的一个实际项目往死里挖。那个项目是一个基于 Vue 3 的后台管理系统我在里面承担了权限路由模块、动态菜单和几个数据可视化大屏页面的开发。第一个问题是“项目里权限路由是怎么实现的”。我用了非常标准的方案后端返回角色权限码列表前端根据权限码动态生成可访问的路由表再用router.addRoute动态添加路由。他追了一句“打包的时候addRoute的路由路径也打包进了主 bundle 里权限控制不就没有意义了吗”这个问题我当时愣了一下确实没想过。后来我们一起讨论才意识到如果关心包体积和安全性应该用动态import的方式懒加载组件这样addRoute添加的路由会被单独分包只有对应权限的用户才会加载到对应代码。这个点之前完全在我的准备范围之外属于被面试官引导着打开的盲区。第二个问题是“动态菜单怎么实现的”。我讲了根据路由配置递归生成菜单数据的方案包括如何用meta.title和meta.icon控制菜单展示、如何处理二级菜单嵌套、以及如何通过v-if控制菜单显示权限。他又追问了一个很刁钻的角度如果某个菜单没有配置meta.title你的递归函数处理后的结果是什么样的。我仔细想了一下回答会渲染成一个没有标题的菜单项但更合理的做法是在递归时对meta做默认值兜底保证没配置的字段不会造成渲染异常。这轮面试给我的最大感受是面试官把你简历上的每一句话都当作你真实写过的东西来考所以简历上不要写自己只是“看过文档”的东西。任何一条项目描述背后都必须准备好几个对应场景的问题。比如写了“使用 WebSocket 实现实时消息推送”就得能说清楚心跳重连怎么做的、断线重连时消息会不会丢、服务端推送的消息格式是怎么约定的。3.3 综合面个人成长、学习能力和对业务的看法三面是综合面面试官是前端技术团队的 leader整体氛围比前两面轻松很多但问的问题一个比一个需要思考深度。开场不是自我介绍而是抛出来一个开放问题“你平时是从哪里获得前端开发相关知识的一年前和现在有什么变化”。这个问题很常见但考验的是你有没有真实的学习习惯。我的回答是一年前基本靠看视频课程和博客文章跟着教程一步步敲代码现在更习惯直接读官方文档、翻源码、看一些高质量周刊和仓库的 issue 讨论因为文档和源码是最新的一手资料博客文章往往存在滞后。之后他问了一个让我印象深刻的问题“如果你现在加入团队前端项目里有一个长期存在的性能问题打开页面要 5 秒你会从哪些角度开始排查”。这题不是考死知识而是考排查思路的完整性。我当时的回答是从网络请求、资源体积、代码执行效率三个方向分步去查先看 Network 面板里有哪些请求耗时高再看打包产物里有没有体积异常大的依赖然后用 Performance 面板定位是否有长任务阻塞了渲染最后考虑是否可以做首屏懒加载或骨架屏。他补充说实际业务里的性能问题很多时候不在代码本身而在接口返回的数据量、图片资源没有做 CDN 压缩这些偏工程的细节上。三面结束后 HR 又问了几个常规问题比如为什么选择前端方向、平时怎么安排时间、有没有考研的打算、能实习到什么时候。这里我的建议是如实回答但尽量往稳定的方向说。比如能实习的时间直接说具体期限不要含糊其辞这会让对方在资源协调上更容易决策。4. 几道印象深刻的题目拆解不是死记硬背而是真正理解背后的设计思路面完之后我把所有被问到的问题整理了一遍挑出几个我个人觉得最有价值的题目按面试时的回答和后面的复盘重新拆解了一遍。这些题不仅这家公司会问很多前端实习岗面试里都会出现值得花时间彻底弄懂。4.1 手写Promise.all理解静态方法背后的时序逻辑这道题在实习生面试里出现的频率极高。表面上是考察 Promise 基础实际上是在考察对异步并发控制的理解。我当时的实现思路是function promiseAll(promises) { return new Promise((resolve, reject) { const results []; let count 0; promises.forEach((promise, index) { Promise.resolve(promise).then((value) { results[index] value; count; if (count promises.length) { resolve(results); } }, reject); }); }); }写完后面试官重点问了两个问题第一为什么用results[index]而不是results.push(value)这个问题的关键是如果某个 Promise 先 resolvepush 的顺序就和传入的顺序不一致了最终结果要按照原始顺序排列。第二如果promises是一个空数组这个实现会不会有问题会的话怎么改。空数组的情况是count初始值为 00 0成立会直接resolve([])其实是没问题的。但有的实现里会在forEach外单独判断空数组也是可以的。追问环节他还让我扩展一下如何给Promise.all加上“并发数限制”的能力。这个就是进阶题了我当时说了思路维护一个当前执行数计数器和待执行任务队列每次发起一个新任务时检查当前执行数是否达到上限没到就继续执行到了就等在队列里某个任务完成后从队列里取下一个继续执行。这种带有任务调度思维的题目我在面试前专门练过类似实现所以这一环节答得比较顺利。4.2 场景题从需求到组件设计考察的是工程化思维这家公司的二面和三面都有场景设计题其中最典型的是二面的那道“如果要在系统里做一个全局的消息通知组件支持成功、失败、警告三种类型并且任何页面都能调用你会怎么设计”。这种题没有唯一答案面试官想看到的是你如何把一个模糊的需求拆成可实现的模块。我当时的回答分了四层。第一层是 API 设计提供一个notification.success(message)这样的方法同时支持传入配置对象形式方便灵活扩展。第二层是渲染方式不直接写在某个页面里而是维护一个单独的通知容器用函数式调用的方式来创建组件实例这样任何页面都能通过导入方法直接使用不需要在每个页面都引一个组件。第三层是样式和交互三种类型对应不同的图标和颜色自动关闭的时间可以由参数控制鼠标悬停时暂停关闭计时。第四层是工程化用单例模式避免容器重复创建用队列管理多条通知的堆叠顺序。面试官听完后问了一个问题“如果业务方提了一个需求通知里要加一个‘查看详情’的按钮点击后跳转到指定路由你现在的设计能支持吗”。这个问题考验的是我有没有在 API 设计里留出扩展点。我当时的回答是可以在配置对象里加一个onClick回调字段或者让用户传入一个完整的 VNode 作为通知内容这样就能在通知里渲染按钮并绑定事件。他听完点了点头这个场景题的完整度他心里已经有了判断。4.3 CSS 高频题BFC 到底是什么为什么面试官爱问在众多前端开发面试题里CSS 相关的问题往往不被重视但真正问起来却是最能拉开差距的。这家公司的一面问了一道“说说 BFC它会解决什么问题”。我简单回答了定义之后重点讲了三个高频应用场景清除浮动、防止外边距合并、以及自适应两栏布局。针对每个场景我都举了具体的代码例子清除浮动父元素内子元素全部float: left导致父元素高度塌陷给父元素设置overflow: hidden或display: flow-root触发 BFC父元素就能包住浮动子元素。防止外边距合并两个相邻元素的margin-bottom和margin-top会合并成一个更大的边距给其中一个元素包一层触发 BFC 的父容器就能隔开。自适应两栏布局左侧固定宽度并浮动右侧建立 BFC 后不会与左侧重叠从而实现自适应。我特别想说一点CSS 题的价值不在于你会不会背 BFC 的触发条件而是在实际问题里能不能想到用它。很多同学会把overflow: hidden当作“清除浮动的必加属性”来背但不知道它背后的原理是创建了 BFC下一次换成display: flow-root就一脸懵。建议复习时把每个 CSS 属性的“是什么”和“解决了什么”成对记忆这样被追问时能答得很有底气。5. 复盘时间这一场面试暴露出的问题和我踩过的坑面试结束当天晚上我趁着记忆还热乎把整场面试从头到尾过了一遍整理出几个准备上的盲区和临场发挥的问题。这些东西比面试题本身更值得写下来。5.1 我以为会考但完全没考的内容面试前我花了不少时间刷算法题准备了几道常见的数组和字符串处理题目但这家公司全程没有问传统意义上的算法题。不是说不该刷算法而是需要看清岗位的信号实习岗面试更看重基础知识和项目思维的结合纯算法题在中小团队前端岗出现的概率并不高。如果时间有限与其把大量时间花在刷题上不如把 JavaScript 核心概念和 Vue 原理吃透性价比更高。另外我还准备了大量 CSS 复杂布局面试题包括圣杯布局、双飞翼布局、Grid 网格布局等结果一道都没考。反而是最基础的 BFC 被问了一道答得还行。这给我的启发是不要把宝押在某几类题目上基础知识的覆盖度才是实习面试的底线。如果某个知识点面试官没问不代表没用只是这次运气好。5.2 实际考了但我准备不足的地方最明显的盲区是二面那个“动态路由懒加载和权限安全的关系”问题。我准备了权限路由的实现方案但没往“打包分割”和“安全边界”这个方向想。面试官提出来之后我才意识到权限控制不只是“在菜单层不显示无权限入口”这么简单还包括“未授权页面不能直接访问”“未授权代码不能加载到浏览器”。这块在真实的业务落地上还需要配合后端接口鉴权来兜底前端权限只是体验层面的优化。另一个准备不足的点是性能优化相关的场景题。我能说出代码分割、懒加载、CDN这些关键词但让他问得更具体时我表达得不够细腻。比如“首屏白屏时间过长”的排查我只说了要看请求和资源但没有提到“先确认是网络耗时还是渲染耗时”“用 Performance 面板看 Main 线程的长任务”“用 Lighthouse 跑一轮性能报告”这些具体的判断手段。这暴露了我对性能问题缺少真实的排查经验更多是靠知识点拼凑回答。5.3 关于用 AI 辅助工具准备面试的体会现在前端面试准备过程中已经有相当一部分同学在用 AI 工具来当自己的“陪练”。我在这次面试前也用过相关工具来找面试题和模拟回答比如让 AI 给我出事件循环的输出题、让 AI 帮我 review 我写的防抖函数有没有边界问题。这里我特别想提醒一句AI 工具是很好的镜子但千万别让它变成拐杖。我自己的体会是把 AI 当作“提问机器”而不是“答案机器”效果更好。用完它生成的题目一定要自己动手写一遍代码或者口述一遍思路再让它指出问题。如果每次都直接看答案很容易陷入“我看了就会其实根本不会”的假象。面试时真正要把思路组织成语言讲出来和脑子里有一个模糊的印象完全是两回事。我在面试前几天每天都会挑两个手写题对着空气讲一遍练到能流畅说出“为什么这样写”才算过。6. 针对前端实习岗面试我的实操建议与后续调整面完这场之后我还缓了一天才写这份面经。一方面是复盘那些答得不够好的部分需要时间沉淀另一方面也在思考下一场面试该怎么调整策略。下面这几条建议是基于我这次真实经历的总结不保证适合每个人但应该对准备前端开发实习生面试的同学有参考价值。第一简历上的每一个技术点都要准备至少三个“为什么”为什么用这个技术、为什么不用另一种方案、这个方案有什么局限。比如你写了 “用 Vuex 做状态管理”面试官可能会问为什么不用provide/inject、为什么不直接 props 层层传、Vuex 的 state 和组件内部ref的区别是什么。这些“为什么”想清楚了项目深挖面就不会慌。第二准备面试时把“说”和“写”结合起来。视觉记忆是很不可靠的看懂了和能写出来是两码事能写出来和能讲明白又是两码事。我面试前把常用手写题全部按“代码 注释 口述重点”的方式整理了一遍比如防抖节流、深拷贝、数组去重、事件总线。整理完再对着手机录音讲一遍回听的时候你会发现很多“这个地方我好像没讲清楚”的瞬间这就是需要补的部分。第三多积累一些真实业务里的细节哪怕是在自己写的小项目里。比如我在自己的项目里处理过“搜索输入防抖 请求竞态”的问题知道怎么用请求序号或 AbortController 避免旧请求覆盖新请求的响应。这种细节在面试时被问起比单纯说“我会用防抖”有感染力得多。第四不要忽略高频低难度题目的熟练度。什么“盒模型有哪两种”“GET 和 POST 的区别”“Vue 生命周期有哪些”这类看起来很简单的问题反而容易在面试时答得不够完整。我自己的方法是每道基础题都按“先一句话结论、再展开细节、最后举例说明”的形式组织回答这样不管面试官要不要细问你都能有一个完整的表述结构。总结起来这次前端开发实习生面试是我年后四场里面得最有收获的一场。虽然最终结果还在等通知但通过完整复盘我已经明确了自己下一阶段要补的方向动态路由权限的完整方案、性能排查的真实工具链、以及在讲项目时“先结论后细节”的表达结构。希望这篇面经对正在准备前端开发面试的同学有帮助也祝大家都能在春招里拿到心仪的实习 offer。
返回列表