ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

前端面试高频八股文:Vite脚手架、HTTP缓存与XSS实战解析

2026/9/1 8:54:04 拓冰建站 浏览量
前端面试高频八股文:Vite脚手架、HTTP缓存与XSS实战解析 把时间拨回到今年三月我蹲在宿舍阳台接完最后一通面试电话手心全是汗。四十分钟里面试官从我的Vite脚手架一路追问到DOM型XSS的触发链路中间穿插了三次关于HTTP缓存的连环设问。挂电话的那一刻我知道这场我准备了整整两个月的暑假实习求职终于有了着落。我是某大专院校大二的前端方向学生学历不够亮眼但我不想把简历投出去就听天由命。这篇实录把我准备和经历的关于脚手架搭建、HTTP、XSS等高频八股文问题连同我的复盘思路完整写出来给同样想冲暑假实习的大专生或者低年级前端做个参考。1. 为什么大专大二就把自己扔进面试场1.1 我的情况学历劣势怎么变成时间优势先交代背景免得大家觉得我在讲虚的。我是计算机应用技术专业的大二学生前端自学了一年半。HTML、CSS、JavaScript 基础、Vue3、Vite、Git 这些算熟练Node.js 会一点没有正经的实习经历简历上放着两个项目一个从零搭的个人博客一个跟着教程做的管理后台。说实话靠这些东西投大厂暑期实习我自己都知道简历关大概率过不了。但我算明白了一笔时间账大专是三年制大二暑假实习完之后大三上学期还能继续实习甚至校招季之前就能攒下将近一年的实际经验。而本科生大多数只能暑假来两个月刚上手就要走HR 其实很头疼。所以我在投递时把简历上的个人简介改成了“大专大三学制支持长期实习可尽快到岗实习周期可覆盖半年以上”。这句话在后来几场面试里都被面试官单独拎出来问过明显是加分项。学历劣势是客观存在的但不能只盯着劣势看。我给自己定的策略是既然学历拼不过那就拼“到岗时间灵活”和“基础功底扎实”这两点。而基础功底就体现在那些让人头疼的八股文能不能答出深度。1.2 面试准备的总体策略别贪多往深里挖准备阶段我犯过一个典型错误——什么都想看。红宝书翻了一半就扔了刚看完闭包又去刷 Next.js 教程结果一周下来脑子里全是碎片面试题一道也答不完整。后来我冷静下来把面试常考的内容分成了“必须吃透”和“了解即可”两档。必须吃透的包括JavaScript 核心作用域、闭包、原型链、事件循环、异步、HTTP 相关内容、前端安全XSS 和 CSRF、Vue3 核心原理响应式、虚拟 DOM、diff、脚手架和工程化。了解即可的包括Node.js 进阶、Webpack 深度配置、TypeScript 高级类型体操、浏览器渲染的每个细节。事实证明这个策略是对的。面试官对大专生本来就不会问特别偏的知识他们更想看你的基础扎不扎实、有没有真实的项目经验、遇到问题能不能自己解决。与其一百个知识点每个都只知道名字不如把三十个核心知识点往深里挖三层。比如“HTTP 缓存”不能只背出“强缓存和协商缓存”两个名词要能把整个决策链路讲清楚最好还能画出来。2. 脚手架搭建面试官到底在考什么我的个人博客项目是在一个很尴尬的情况下诞生的觉得 Vue CLI 太重又觉得从头配 Webpack 太折磨后来发现 Vite 真的香就基于 Vite 从零搭了一个博客项目。这个项目成了我简历上最硬的素材因为面试官只要一问“说说你的项目”我就有无数个真实的细节可以讲。2.1 从零搭一个 Vite 脚手架的完整思路面试官问“说说你怎么搭建的”时我一开始以为他们只想听步骤后来才明白他们真正想听的是“你知不知道这一步为什么要这么配”。我当时搭建的完整流程是这样的先执行npm create vitelatest创建 Vue3 JavaScript 的项目骨架然后安装 Vue Router、Pinia接着做目录结构重构——把 src 拆成 assets、components、composables、router、stores、styles、utils 这些模块。然后配置vite.config.js里的路径别名、开发服务器代理、打包配置最后装了 ESLint 和 Prettier 统一代码风格。关键不是这些步骤而是每一步背后的原因。比如为什么用作为别名而不是直接写相对路径——因为项目变大之后../../../components/xxx.vue根本没法维护。又比如为什么开发服务器要配代理而不是直接跨域——因为生产环境里前端和后端通常是同源部署的开发环境模拟同源状态才能提前暴露问题。Vite 的依赖预构建机制我也被问到过。面试官问我“为什么用 Vite 启动项目那么快”我答上来是因为 Vite 利用浏览器原生 ES Module开发时不用打包整个项目只对浏览器请求到的模块按需编译同时用依赖预构建把 CommonJS 转成 ESM并且把几百个小模块合并成单文件减少浏览器请求数量。这里我还顺带对比了 Webpack——Webpack 在开发时要把所有模块先打包成一个 bundle 再启动项目一大就慢Vite 是在请求时才编译所以冷启动和热更新都更快。2.2 面试中被追问的工程化细节面到第三家公司的时候面试官逮着脚手架问了一连串工程化细节很多是我之前没想到的。第一个追问是“那你项目的环境变量怎么管理的”。我当时项目里只有 development 和 production 两种环境后来面试官提示我可以再加一个 test 环境。不同环境有不同的 API 地址、不同的调试开关用.env.development、.env.production、.env.test来区分通过import.meta.env.MODE读取。说实话这个我在自己项目里没做是面试前临时补的但面试完我觉得这个确实很重要——真实项目里多环境管理几乎是必须的。第二个追问是“第三方库按需加载你怎么处理”。我的博客用了 Element Plus刚开始直接app.use(ElementPlus)全量引入打包体积炸到了 900 多 KB。后来改成按需引入配合 unplugin-auto-import 和 unplugin-vue-components 两个插件Element Plus 的组件在模板里用了才会自动打包进去。我还做了路由级代码分割就是() import(./views/Home.vue)这种写法让首屏只加载首页的代码。这一套下来最终包体积从 900 多 KB 降到了 300 KB 以内这个数字我记得很清楚。第三个追问是关于“打包后部署到服务器发现样式丢失”的问题。这个我没遇到过但我看过相关文章就照实说了大部分原因是 CSS 代码被拆到独立文件后某些浏览器的缓存机制导致加载到旧版本或者抽离的 CSS 顺序不是预期顺序。面试官点点头没继续问说明我答到了点子上。2.3 我在脚手架项目里挖过的坑这里分享一个我真实踩过的坑现在想起来都觉得好笑。我配置代理的时候写的是server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true, rewrite: (path) path.replace(/^\/api/, ) } } }结果怎么调都 404接口一直报错。排查了一下午最后发现后端接口的路径是/api/user/list本来就不需要去掉/api前缀我加了个rewrite把前缀删了请求变成/user/list后端匹配不到当然 404。这个坑让我学到一条经验代理配置的rewrite不是必写的只有前后端路径前缀不一致的时候才需要。现在每次写都会先搞清楚后端接口真实的路径结构再决定要不要 rewrite。后来面试里被问到代理配置我都会主动讲这个案例面试官通常都会笑一下说“这个坑很多人踩过”。另一个坑是 Vite 版本升级带来的配置差异。我最初用的是 Vite 4后来升级到 Vite 5server.proxy的配置没有变但部分插件不兼容了比如某个 SVG 插件在 Vite 5 下直接不支持。这种兼容性问题没有捷径只能看官方迁移文档我在面试里也如实说了“升级依赖的时候碰到过兼容性问题通过查看官方 changelog 解决了”。3. HTTP 八股文别只背状态码要会讲完整链路HTTP 是前端面试的必考题也是很多人都只背了表面、一追问就穿帮的领域。我自己在准备时走了不少弯路总结出了几条经验。3.1 从 URL 输入到页面渲染一条线串起所有考点我第一次面试的时候面试官问“从输入 URL 到页面展示的完整过程”我按标准答案背了一遍DNS 解析、建立 TCP 连接、发送 HTTP 请求、服务器返回、浏览器渲染。面完我就知道这答案太平了因为太像标准答案一点个人理解都没有。后来我把这条链路上每一个环节的细节都补齐了。DNS 解析要讲到递归查询和迭代查询的区别TCP 连接要讲到三次握手为什么是三次而不是两次HTTP 请求要讲到请求头和请求体的组成浏览器渲染要讲到 DOM 树、CSSOM、渲染树、重排重绘。举个例子三次握手为什么是三次我的理解是三次握手本质上是在确认双方都有发送和接收能力。第一次客户端发 SYN服务器知道了客户端有发送能力、自己也有接收能力第二次服务器发 SYNACK客户端知道了自己有发送和接收能力、服务器也有发送能力第三次客户端发 ACK服务器确认了客户端有接收能力。如果是两次握手服务器没法确认客户端能不能接收数据所以两次不够。还有一次我问自己“那为什么要挥手四次”因为 TCP 是全双工的客户端和服务端都能独立发送和关闭连接。第一次挥手是客户端说“我发完了”第二次是服务端说“我收到了但我还有数据没发完”第三次是服务端说“我也发完了”第四次是客户端说“我确认了关闭吧”。每一端都需要独立的“我发完了”和“你确认了”两个步骤所以是四次。这个逻辑顺下来就很好记。3.2 HTTP 缓存强缓存和协商缓存的判定逻辑HTTP 缓存是高频考点面试官几乎必问。我整理的记忆方法是把缓存理解成“要不要去问服务器”的两个等级。强缓存是在本地判断的如果命中了就直接用本地缓存根本不发请求。它靠Cache-Control比如max-age3600或Expires服务器返回 GMT 格式的过期时间来实现。这里有个细节Cache-Control的优先级高于Expires因为 HTTP/1.1 的规范更倾向用前者。强缓存过期之后进入协商缓存阶段。浏览器带着缓存的标识去问服务器“这个资源还能用吗”服务器通过Last-Modified和ETag来判断。Last-Modified是文件的最后修改时间浏览器下一次请求时带上If-Modified-Since服务器对比时间决定返回 304 还是重新返回 200 加新内容。但是Last-Modified有个问题文件修改时间变了但内容没变比如只改了个权限也会触发重新下载所以有了ETag。ETag是根据文件内容生成的哈希值If-None-Match带上旧 ETag服务器比对内容指纹内容没变就返回 304。面试的时候我把整个流程画成了一个决策链请求一个资源 → 先看强缓存是否命中 → 命中就直接用 → 没命中就带协商缓存标识问服务器 → 服务器返回 304 就用缓存 → 返回 200 就更新资源。这么答基本能把面试官的追问扛住。我记得有一场面试面试官还追问了“那强缓存失效之后ETag 和 Last-Modified 同时存在时服务器以哪个为准”。标准答案是大多数服务器会优先校验If-None-Match也就是 ETag因为 ETag 比 Last-Modified 更精确。理由我刚才也说过Last-Modified 的粒度是秒级而且内容没变也可能变时间ETag 是基于内容指纹的能更准确地判断内容是否真的变了。3.3 HTTP 和 HTTPS对称加密与非对称加密的合作关系“HTTP 和 HTTPS 的区别”这道题我面了 6 家问了 4 次。标准答案大家都知道HTTPS 是 HTTP TLS 加密解决的是明文传输被窃听、报文被篡改、身份被冒充这三个问题。但面试官喜欢追问的是“TLS 靠什么加密”。这个很多人只会说“非对称加密”但实际上完整的回答是“非对称加密 对称加密混合加密”。为什么不用纯非对称加密因为非对称加密比如 RSA计算开销大一个完整的 HTTPS 会话里传输的都是大块数据全部用 RSA 加密性能扛不住。为什么不用纯对称加密因为对称加密的密钥本身怎么安全地传给对方是个死循环——你不能用同一个密钥把密钥发出去。所以 TLS 的混合加密逻辑是这样的先用非对称加密完成密钥交换保证对称加密的密钥能安全传到对方手里后续通信全部用对称加密兼顾安全和性能。这里面还有数字证书的概念面试官如果再追问“怎么确保证书不是伪造的”就要讲到 CA 签发证书、签名验证的信任链——浏览器内置了 CA 的公钥拿到证书后用 CA 公钥验证签名验证通过才信任证书里的公钥。3.4 HTTP 状态码高频状态码的实战意义状态码这块我是按照“面试官常问 实际开发碰得到”的标准来准备的。我把它们分成了三组记忆。第一组是 2xx200 正常、204 没有返回体、206 断点续传或分片下载。206 在实现大文件下载、视频播放拖动进度条时会遇到。我的简历上写了用 Web Worker 上传大文件面试官对这个经历很感兴趣因为这里用到了类似的分片机制。第二组是 3xx301 永久重定向、302 临时重定向、304 协商缓存命中、307/308 重定向时保留请求方法和请求体。301 和 302 有个经典坑——302 重定向时浏览器可能把 POST 改成 GET所以 HTTP/1.1 引入了 307 和 308307 保留方法和 body。第三组是 4xx 和 5xx400 参数错误、401 未认证、403 无权限、404 不存在、405 方法不允许、429 请求太频繁500 服务器内部错误、502 网关错误、503 服务不可用、504 网关超时。我在项目里遇到过 504后来发现是后端接口处理时间太长Nginx 的默认超时时间到了直接在 Nginx 配置里把proxy_read_timeout调大了。面试里被问到“502 Bad Gateway”的时候我还结合我踩过的坑补充了一句502 是网关收到了但上游服务器没给出有效响应最常见的情况是后端服务挂了或者 FastCGI 配置不对。有一次我自己用本地代理调试接口返回502 Bad Gateway我查了一圈发现是后端服务没启动启动后就好了。这种实战细节说出来面试官会觉得你不是纯背八股。4. XSS 面试题原理、分类、防御三板斧XSS跨站脚本攻击是我准备面试时最头大的一个话题因为网上资料太多太杂而且很多都讲得很深比如各种绕过技巧我一开始抓不住重点。后来我把 XSS 的考点收敛成“分类 原理 防御”三个方向面试基本够用了。4.1 三种 XSS 怎么区分面试怎么答XSS 的本质是攻击者把恶意脚本注入到页面中在受害者的浏览器里执行。面试官喜欢问“XSS 有哪几种类型”正解是反射型、存储型、DOM 型三种。反射型 XSS 的特点是恶意脚本通过 URL 参数传入服务端把参数原样拼进了 HTML 返回值里浏览器解析后执行了恶意脚本。它的名字“反射”就很形象——你发给服务器的参数服务器原封不动“反射”回来。这种 XSS 一般通过钓鱼链接传播。存储型 XSS 的特点是恶意脚本被持久化存储在服务端比如写入数据库。用户正常浏览时服务端从数据库取出数据拼进页面恶意脚本跟随正常数据一起被渲染执行。评论区、留言板是重灾区——攻击者提交一条评论里面藏着script标签以后所有访问这个页面的人都会中招。存储型 XSS 危害最大因为没有特定受害者是“无差别攻击”。DOM 型 XSS 有点特殊它的恶意代码不经过服务器而是前端 JavaScript 在操作 DOM 时把用户可控的数据用innerHTML等方式插入了页面。比如地址栏的 hash 值、window.name、localStorage里的内容如果直接用innerHTML渲染就给了 DOM 型 XSS 可乘之机。面试时我通常用一个表格来对比三种类型面试官会觉得你逻辑很清晰类型注入位置是否经过服务器存储位置典型场景反射型URL 参数是不存储搜索页、URL 拼接回显存储型数据库是持久化存储评论区、留言板DOM 型前端 DOM 操作否浏览器本地hash 路由、innerHTML 渲染4.2 面试官连环追问的防御细节XSS 的防御万变不离其宗不信任用户输入不信任任何将被插入到 HTML 里的数据。具体有三板斧输入过滤、输出转义、CSP。输入过滤是对用户提交的内容做校验和过滤把script、javascript:这类危险内容剔除。但这里有个很重要的细节输入过滤不能作为唯一的防御手段因为过滤很难做到万无一失总有绕过的方法比如各种编码组合、大小写混写、事件属性绕过。输出转义是更核心的手段。编码的时候要区分上下文——HTML 标签内、属性内、JavaScript 代码内、CSS 内转义规则完全不同。使用框架的自动转义功能比如 Vue 模板里的{{}}插值会自动转义、使用textContent而不是innerHTML、避免使用v-html这些都是最基础的防护。面试时我模拟过一个场景用户在输入框里提交了img srcx onerroralert(1)如果前端直接innerHTML插入页面加载时必然弹窗。如果换成const userInput document.getElementById(input).value; const container document.getElementById(container); container.textContent userInput;这段代码输入什么就显示什么img不会变成真实标签只会显示为纯文本攻击直接失效。这个例子虽然简单但说明了核心逻辑不给浏览器解析用户输入的机会。面试官还会追问“如果业务上必须用 v-html 怎么办”。正确的思路是服务端先对内容做严格的白名单过滤用 DOMPurify 这类库清洗而不是自己写正则然后再插入。同时配合 CSP 来限制脚本来源这样即使有遗漏恶意脚本也执行不了。我自己项目里处理富文本内容时就是 DOMPurify 清洗后再渲染这个实践经历在面试里很加分。4.3 一个容易被忽略的安全点CSPCSP内容安全策略在面试中出现频率在变高可能因为我面试的时间点正好赶上一些大厂的安全事件。CSP 的核心思想是告诉浏览器“我只能信任这些来源的内容”通过响应头Content-Security-Policy来配置。比如这样一行配置Content-Security-Policy: default-src self; script-src self意思是资源默认只能从同源加载脚本也只能从同源加载。如果攻击者注入了第三方域名的恶意脚本浏览器会直接拦截不掉执行。CSP 还有一个更狠的用法禁止内联脚本用script-src self nonce-随机值配合 nonce只有带正确 nonce 的script标签才会被执行。我在自己项目里试着给博客加过 CSP配置简单但调试麻烦——各种第三方统计脚本、CDN 资源都变成“不信任”的需要一点点加白名单。面试时我如实说了这个体验面试官很认可因为他知道真实项目里上 CSP 确实是个精细化活。CSP 还有一个容易被忽视的细节default-src和script-src的覆盖关系。script-src没写的时候才用default-src兜底一旦写了script-src self那么脚本的规则就只受script-src控制。面试时能把这层覆盖关系讲清楚说明你真的理解了 CSP而不只是背了一行配置。5. 面试实录一次 35 分钟的电话面试全复盘光背知识点没用我把自己一次比较典型的真实面试过程复盘出来你会发现面试官问的问题本身不难难的是你怎样把脑子的知识组织成输出。5.1 开场自我介绍怎么讲不虚那次电话面试面试官第一句就是“你先介绍一下自己吧”。我之前的版本是这样的“我叫 XX是大专大二学生自学前端一年多了会 Vue会用 Vite 搭项目平时喜欢写博客。”这个介绍最大的问题是没有区分度和大多数人的自我介绍一模一样。后来我把自我介绍改成三段式——我是谁 我做了什么 我来应聘的原因“我是 XX目前是大专大二的学生主学前端大概一年半。技术栈上 Vue3、Vite、TypeScript 的基础使用没问题Git 和 ESLint 这些工程化工具也都用得比较熟。自己做了一个个人博客项目从零搭的 Vite 脚手架做了路由懒加载、代码分割这些性能优化最近还在项目里补了 XSS 的防护措施。我选择这个时间找暑假实习是因为大专是三年制我实习完之后大三还能继续实习有充足的时间和精力来打磨自己的实战能力。”这段介绍基本涵盖了技术栈、项目、主动性三个关键信息而且特意突出了“时间优势”这个差异化点后面好几个面试官都对我的时间规划表示肯定。5.2 面试官追问后的思考路径那次面试的前半段比较顺利但到中间有个卡点。面试官问“你的项目里用了事件委托吗说说看。”我以前的理解是事件委托就是“给父元素绑定事件利用冒泡让子元素触发父的事件”但我只是知道这个概念自己写代码时很少主动用。所以我不但没答好“为什么用事件委托”连反问“从父元素怎么区分是哪个子元素点出来的”都答得支支吾吾。正确答案是在事件处理函数里读event.target判断它的标签名、类名或 data 属性再执行对应的逻辑。面完之后我专门把事件委托的几个高频追问理了一遍为什么要用事件委托答性能更好尤其列表很长或频繁增删节点时不需要给每个子元素单独绑定内存占用更小而且子元素动态新增时不用重新绑定。冒泡到顶层不会浪费吗答单个事件处理函数的开销远小于成千上万个事件处理函数的开销所以总体上性能是更好的。如果要阻止冒泡用stopPropagation。哪些事件不会冒泡答focus、blur、mouseenter、mouseleave这些所以它们不适合用事件委托。这些内容其实都是 JavaScript 基础八股文但那次面试暴露了我只背定义、没有实操理解的短板。5.3 我答崩的一道题从失败里学到的那次面试里我真正完全答崩的是一道关于闭包的题。面试官给了段代码for (var i 0; i 5; i) { setTimeout(function() { console.log(i); }, 100); }问我输出什么。我知道答案肯定是 5 个 5也想到了用let修复但我解释不了“为什么 var 会导致这个结果”。面试官又追问“如果把 var 换成 let 会怎么样”我说“会输出 0 到 4”但说不清背后的原理。面完我认真补了一次课var声明的变量是函数作用域的for循环里每一轮迭代并不会创建新的作用域而是共享同一个isetTimeout的回调函数在 100 毫秒后执行那时循环早就结束了i已经变成了 5所以打印出来全是 5。而let是块级作用域的每一轮循环都会创建新的绑定回调函数引用的是自己那轮的i所以是 0 到 4。这道题我虽然没有在当时答好但后来我把它的底层逻辑执行上下文、词法环境、闭包捕获变量都弄明白了这比背十道八股文都有用。后面再面试遇到类似的题我都能举一反三。面试中遇到不会的问题千万别慌着瞎编坦诚说“这块我掌握得不够深我理解的是……”然后尽量说出关联的知识点面试官往往会愿意引导你。6. 实习求职的实操建议大专生怎么找到暑假实习最后聊点求职策略层面的东西。这些可能不是面试题但对大专生能不能拿到实习机会影响更大。6.1 简历里写什么项目最加分大专生简历最大的问题不是项目不够“高级”而是项目写得太像课程作业。我见过太多人写“网上商城系统”“图书管理系统”这类项目一看就是培训班或课设面试官连点开的欲望都没有。我的判断标准是项目要能体现你在做的过程中遇到了问题并自己解决了问题。比如我的博客项目我强调的不是“用了 Vue3 和 Vite”而是“为了缩小首屏包体积做了路由懒加载把 Element Plus 改成按需引入整体体积从 900 多 KB 降到 300 KB 以内”。这句话一出来面试官就知道你不是照着教程敲的而是真的在关注性能。简历里还可以写一些面向过程的小细节。比如我在博客项目里做过前端 Worker 上传大文件是把文件切片后用postMessage传给 WorkerWorker 负责把切片转成 base64 或直接发请求主线程不阻塞。这种细节虽然不一定会在面试里被问到但写出来会显得你干活有思路。6.2 投递渠道和时间节奏暑假实习的投递时间比很多人想得要早。我是一月中旬开始投三月份开始集中面试四月底才拿到第一批 offer。很多大厂的暑期实习网申年初就开始了等暑假再投基本凉了。投递渠道上我个人体验是效率从高到低排列内推 公司官网招聘 Boss 直聘/拉勾 学校就业群 牛客网。内推最有效是因为简历可以直接到部门 leader 手上省掉 HR 筛选那层。我没有很强的人脉但我在掘金上关注了几个在目标公司做前端的作者有的作者会发“团队招暑期实习生欢迎直接私聊简历”的帖子这时候我就主动发私信附带一个简短的项目介绍。外包公司要不要去我的建议是如果时间允许可以面一家练手但尽量不要接——外包项目往往接触不到核心业务对前期成长帮助有限而且后续跳槽时外包经历在简历上会被重新审视。小公司的实习只要做的事情是“真前端”而不是“打杂”去也行但薪资和成长预期要放低。6.3 心态调整和退路准备最后一个要说的其实是心态。整个求职过程我经历过一段特别焦虑的时间——投出去的简历大多石沉大海面完一家小公司说“后续通知”就再也没下文身边同学一个个都在刷题找工作那种被拒绝的感觉很容易让人怀疑自己。但回头看我觉得有三件事帮我稳住了心态。第一是给自己设一个时间底线比如“投满 60 家还没 offer我就暂停投递把项目再完善一个月再集中投一轮”。这个底线让每次被拒都变成“方案 A 行不通、换方案 B”的决策而不是盲目焦虑。第二是一边面试一边继续干活。面试的间歇我一直在完善博客项目加了一些小功能比如文章字数统计、阅读进度条这些后来都写进简历更新版。项目每多一个功能下一次面试我多一分底气。第三是准备好“没有暑假实习”的备选方案。我的备选是暑假给自己安排一个系统性学习计划把 JavaScript 全部核心知识点整理成自己的笔记顺便做一个复杂度更高的实战项目。后来拿到 offer这个计划就没用上但我想过就不慌。如果你也是大专或二本的前端学生想趁暑假找个实习我的核心建议是别把自己的学历当成最大的短板你要做的是用项目和实战能力证明“我能干活”然后用时间优势让面试官觉得“招你划算”。剩下的就是一边面一边补面得多了你自然知道哪些地方还没吃透。最后再分享一个小技巧每次面试完趁记忆还热乎马上把面试官问过的所有问题记在备忘录里标注哪些答得好、哪些卡壳了然后当天晚上就把卡壳的问题弄明白。我的第 3 次面试到第 4 次面试之间只隔了三天但就是这次复盘让我在第四场面试里顶住了 XSS 的所有追问顺利拿到了 offer。