
前端面试八股文这两年几乎成了每个前端人的必经关卡。不管你是刚刷完基础准备投简历的应届生还是工作两三年想跳槽的进阶开发打开招聘软件先看到的永远是那几道高频题事件循环输出顺序、闭包内存泄漏、浏览器缓存、Vue 响应式原理。这套东西确实有点“背了用不上、不背过不去”的尴尬但它背后考的其实不是记忆力而是你对 JavaScript 和浏览器运行机制的理解深度。这篇内容我整理了一份高频 100 题的完整知识地图挑出其中最典型、最容易被追问的题目做深度拆解每一题都讲清楚“答案是什么、为什么是这个答案、面试官会往哪个方向继续追问”。适合正在冲刺面试、想系统过一遍前端核心知识点的同学也适合想从八股文里提炼出真正原理的人。1. 先聊清楚前端八股文到底在考什么1.1 面试官为什么要问八股文不少人对八股文有抵触情绪觉得“背这些有什么用工作里又不写”。我一开始也这么想直到我连续面了几十个人自己也坐在面试官的位置上才慢慢理解八股文存在的逻辑。面试官问八股文第一层目的是筛选基础。团队招人是有试错成本的候选人如果连 Promise 的执行顺序都搞不清楚项目里遇到异步竞态大概率也处理不好。第二层目的是观察思维方式。你会发现同样一道事件循环题有人能直接报出答案有人会推导演示一遍还有人会主动补充“在 Node 环境里输出顺序可能不同”——这三类人给出的信号是完全不一样的。八股文本身是死的但你回答它的过程是活的。所以我在整理这 100 题时一直提醒自己每道题不要只记结论要顺着结论往下挖一层弄清楚这个结论是从哪些机制推导出来的。下面这张知识地图就是把 100 题按高频考点归归类方便你对照查漏补缺。1.2 高频 100 题完整知识地图我把平时收集到的前端面试题做了一次分类汇总基本覆盖了绝大多数公司的笔试和一面问题。你可以把这份清单当成一个自查表哪里不熟就重点补哪里。分类题量核心考点HTML / CSS10语义化标签、BFC、Flex 布局、Grid 布局、CSS 选择器优先级、盒子模型、重排重绘、移动端适配、层叠上下文、响应式方案JavaScript 基础25数据类型、类型转换、原型链、闭包、作用域、this 指向、call/apply/bind、new 实现、深浅拷贝、事件循环、Promise、async/await、Generator、模块化、垃圾回收、数组方法、字符串方法、JSON、正则、错误处理ES610let/const、解构赋值、箭头函数、Set/Map、Proxy、Reflect、Symbol、迭代器、扩展运算符、可选链浏览器与网络15从输入 URL 到页面展示、浏览器缓存、HTTP 1.0/1.1/2.0/3.0、HTTPS 握手、同源策略、跨域方案、Cookie/Session/Token、WebSocket、渲染流程、JS 执行机制、存储方案、前端安全、性能指标Vue / React15响应式原理、diff 算法、虚拟 DOM、生命周期、组件通信、路由原理、状态管理、Hooks 原理、Computed/watch 区别、key 的作用、nextTick、插槽、高阶组件、合成事件工程化与性能15Webpack 构建流程、Loader 与 Plugin、Tree Shaking、代码分割、模块联邦、Vite 原理、Babel 原理、Git 工作流、CI/CD、打包体积优化、SSR、微前端、Monorepo、Nginx 部署、前端监控手写题与算法10防抖、节流、深拷贝、Promise.all、数组去重、发布订阅、柯里化、LazyMan、大数相加、二分查找这份清单看着多实际上每一类里都有高频中的高频。我把最容易被反复问到、也最值得深挖的题目挑出来在下面几节里展开讲清楚。1.3 背八股文的正确姿势记忆流程与输出方式很多人背八股文失败不是因为不够勤奋而是方法错了。我见过两种极端一种是把八股文当背诵材料每天对着文档念念到滚瓜烂熟一上机写代码就懵另一种是完全不看八股文觉得工作中“用到再查”结果面试时连最基础的概念都组织不好语言。这两种我都经历过也确实都吃过亏。正确的做法是“三步记忆法”。第一步理解原理把题目对应的机制、规范、源码看一遍第二步用自己的话把原理讲出来假装对面坐着面试官讲一遍录下来回听哪里卡壳第三步结合项目场景把题目编进一个你真实做过的功能里。比如深拷贝这道题不要干巴巴地说“用 JSON.parse(JSON.stringify())”而是说“我之前在项目里做用户编辑表单回显遇到 date 类型被转成字符串的问题后来发现是深拷贝没有处理 Date 类型手写了一段递归拷贝……”你看同样是答一道题有场景的说法信息量完全不同。我在后面每个题目里都会标注“面试官追问方向”你复习的时候多想想这些追问而不是只盯着一问一答的结论。2. 高频核心题精讲JavaScript 篇2.1 事件循环一道经典输出题考穿所有原理事件循环是前端面试里出现频率最高、也最容易翻车的题几乎每一场面试都会遇到。它考察的不只是你对“宏任务/微任务”这两个概念的记忆而是你对 JavaScript 单线程执行机制的完整理解。先看这道经典输出题console.log(script start); setTimeout(() { console.log(setTimeout); }, 0); Promise.resolve() .then(() { console.log(promise1); }) .then(() { console.log(promise2); }); console.log(script end);输出顺序是script start→script end→promise1→promise2→setTimeout。很多人不理解为什么setTimeout(fn, 0)明明设置了 0 毫秒延迟执行顺序却排在两个 Promise 后面。答案是JavaScript 的执行顺序由事件循环机制决定同步代码永远先执行遇到异步任务会分别进入宏任务队列和微任务队列。当前宏任务执行完毕后会清空所有微任务然后才取出下一个宏任务执行。这里有一个面试官特别爱追问的点为什么微任务优先于宏任务从设计初衷来看微任务是为了处理需要在当前任务结束后立即执行的逻辑比如 Promise 的回调、queueMicrotask注册的任务。如果微任务不优先执行Promise 的回调可能被延后到下一次宏任务这对异步语义是有害的。再进阶一点面试官一般会甩出一道 async/await 的题目async function async1() { console.log(async1 start); await async2(); console.log(async1 end); } async function async2() { console.log(async2); } console.log(script start); setTimeout(() console.log(setTimeout), 0); async1(); Promise.resolve().then(() console.log(promise1)); console.log(script end);这道题的输出在旧版和新版引擎里不太一样老答案里promise1会先于async1 end输出原因是旧版 V8 对 await 的实现会额外创建一层微任务。新版本做了优化async1 end的微任务注册时机提前所以输出顺序变为script start→async1 start→async2→script end→promise1→async1 end→setTimeout。注意面试时如果遇到这道“顺序有争议”的输出题可以主动补一句“这个顺序在不同浏览器内核版本里可能有差异”这反而是一个加分项说明你真的关注过引擎实现。备考事件循环的独家心得不要只看输出要自己画一遍执行过程。每当遇到一段异步代码先判断它是宏任务还是微任务标注入队时间再模拟取出和执行。多画几道题之后你会发现规律非常清晰。2.2 闭包定义、作用域链与内存泄漏边界闭包这道题十场面试九场问但很多人回答得过于模板化“函数内部返回函数外层函数执行完之后内层函数仍然能访问外层函数的变量。”这个说法对但不完整。闭包的本质在于函数在定义时会保存一份对定义时所在作用域链的引用。当函数作为返回值被带出外层作用域之后这份引用仍然保留于是内部函数可以继续访问外层函数的局部变量。这个时候外层函数的变量不会被垃圾回收机制回收因为作用域链上仍然存在一个活着的引用。面试官通常会有两个追问方向。第一个方向是“闭包会不会造成内存泄漏”。网上很多文章把闭包和内存泄漏直接画等号这是不准确的——闭包本身不会引起内存泄漏只有闭包内引用的变量长期存活、且你又不再需要它时才会造成不必要的内存占用。比如function createClosure() { const heavyData new Array(10000000).fill(x); return function () { console.log(heavyData.length); }; } const closureFn createClosure(); // 如果后面不再使用闭包heavyData 就白白占着内存解决方式也很简单不再使用时把closureFn null闭包被释放整个作用域链上的变量也随之失去引用。第二个追问方向是“闭包的实际应用场景”。这里建议准备两三个真实场景面试时比背概念有用得多。最常用的是防抖节流、柯里化、模块化私有变量。我在项目里最常用的是封装一个带私有状态的组件逻辑比如计数器、缓存管理器把变量放在闭包里只暴露操作方法外部无法直接修改内部状态。我提醒过很多人闭包这道题千万不要只回答“什么是闭包”一定要主动往下延伸把作用域链、垃圾回收机制、实战应用串起来讲。一段结构完整的回答大概是先说闭包的定义再解释它依赖的机制然后举一个项目里的场景最后补一句“使用时要注意变量的生命周期”。这四层答完整这道题基本稳了。2.3 深拷贝手写实现与序列化方案对比深拷贝是手写题里的常青树也是能拉开差距的一道题。最常见的答案是用JSON.parse(JSON.stringify())简单、快多数场景下够用。但面试官一定会追问它的局限性建议至少记住四点不能处理undefined、Symbol、function这些值会被直接忽略或转为null不能处理Date会被转成字符串不能处理RegExp、Map、Set不能处理循环引用会直接抛错。如果题目要求手写从递归版本写起比较稳function deepClone(obj, map 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); 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用来解决循环引用。为什么要用 WeakMap 而不是 Map因为 WeakMap 的键是弱引用不会阻止垃圾回收和闭包题里的内存考量是同一个思路。我写完这段后通常会补一句这个写法没有处理Symbol属性和Map/Set如果面试官追问我再继续补全。面试官偶尔会问“数组能用相同方式拷贝吗”或者“能处理__proto__吗”这些都是一环扣一环的细节。我的经验是手写题不需要追求一次写满分但需要做到主流程正确、边界情况能讲清楚给出至少两种改进方向。这样面试官能明显看出你是真的会而不是背了一段模板代码。3. 高频核心题精讲浏览器与网络篇3.1 浏览器缓存强缓存与协商缓存的全链路解析浏览器缓存几乎是前端面试里的必考题不只是前端很多后端面经里也会出现。缓存考察的本质是你是否理解网络请求的性能优化手段以及你能否在实际项目里正确地设置缓存策略。先说强缓存。服务器在响应头里返回Cache-Control浏览器发现资源还在有效期内就不会发起真实请求直接从本地缓存读取。相关字段有max-age、immutable、no-cache、no-store很多初学者容易把no-cache和no-store搞混。no-cache的意思是允许缓存但每次使用前必须先向服务器重新验证no-store才是完全不缓存。强缓存命中时状态码显示 200来源可能显示from memory cache或from disk cache。前者表示从内存缓存中读取通常出现在页面刚加载完、缓存还没被清除时后者表示从磁盘缓存中读取持久性更强。再说协商缓存。当资源过期强缓存未命中或者响应头设置了no-cache浏览器会带着条件请求头去问服务器“我这个缓存还能用吗”服务器返回 304 表示“资源没变继续用缓存”返回 200 表示“资源变了我重新给你新的”。协商缓存有两对关键字段Last-Modified/If-Modified-Since和ETag/If-None-Match。前者基于文件的最后修改时间实现简单但存在精度问题修改时间只能精确到秒同一秒内多次修改无法区分后者基于文件内容的哈希值判断更准确优先级也更高。实际工作中一般两者配合使用但前端在做缓存策略时更依赖 ETag。我在面了很多人之后发现一个共性问题大多数候选人能说出来“强缓存和协商缓存”这两个词但没法解释清楚“第一次请求时浏览器如何决定缓存策略”和“命中不同缓存时的网络表现”。我的建议是把整个流程连起来讲一遍从浏览器地址栏输入 URL到检查强缓存到发送协商缓存请求到收到 304再到读取本地缓存并渲染。能把这串逻辑讲通这道题才是真正掌握了。3.2 HTTP 从 1.0 到 3.0关键差异与面试话术HTTP 版本演进这道题本质上问的是“为什么 HTTP 需要不断升级每次升级解决了什么问题”。回答的框架比单个知识点更重要。HTTP/1.0 的问题是无连接、无状态每次请求都要建立新的 TCP 连接性能很差。HTTP/1.1 引入了持久连接和管道化但管道化因为队头阻塞问题在浏览器里基本没有真正启用。HTTP/1.1 的主要限制是队头阻塞多个请求共享同一条 TCP 连接前一个请求没有完成后面的请求就得排队等待。HTTP/2.0 的突破是引入了二进制分帧层和多路复用。二进制分帧把请求和响应数据切分成更小的帧多个帧可以在同一个 TCP 连接上交错发送理论上解决了 HTTP/1.1 的队头阻塞。HTTP/2 还有头部压缩HPACK和服务器推送一个是减少重复头部带来的传输开销一个是让服务器主动把资源推给浏览器。但是 HTTP/2 有一个尴尬点TCP 层的丢包重传依然会造成阻塞这就是所谓的 TCP 层队头阻塞。HTTP/3.0 直接换掉了传输层改用基于 UDP 的 QUIC 协议。QUIC 内置了加密默认 TLS 1.3、连接迁移、多路复用和更快的握手能力把连接建立时的 RTT 从 TCP TLS 的约 2~3 次往返降低到 1 次左右。面试时只要能把“TCP 队头阻塞 → HTTP/2 解决应用层 → HTTP/3 解决传输层”这条主线讲清楚就已经超越了大多数候选人。回答这题的话术建议是先给出版本演进的整体脉络再展开每个版本的关键特性最后落脚到项目实践。比如“我在项目里通过 Nginx 检查了 HTTP/2 是否生效并配置了合理的资源合并策略”。这样既展示了知识面又体现了工程化思维。3.3 从输入 URL 到页面展示中间发生了什么这是一道综合性大题几乎能把整个前端知识体系串起来。面试官问它核心是想看你能不能把“网络 浏览器 渲染”三段知识流畅地组织成一条完整链路。我的回答模板分五段。第一段是输入与解析浏览器检查 URL 是否合法补全协议和默认端口判断是否命中 HSTS 强制跳转 HTTPS。第二段是 DNS 解析浏览器缓存、系统缓存、路由器缓存、本地 hosts、递归 DNS 服务器逐层查找把域名解析成 IP。第三段是建立连接TCP 三次握手建立传输通道如果协议是 HTTPS 还要进行 TLS 握手协商密钥然后浏览器发出 HTTP 请求服务器返回响应。第四段是浏览器渲染流程收到 HTML 后解析器将字节流解析为 DOM 树同时解析 CSS 生成 CSSOM 树。这里有个关键点CSS 会阻塞渲染但不会阻塞 HTML 解析JavaScript 则可能被标记为 blocking遇到script标签会暂停解析所以推荐使用defer或async加载脚本这正好能和性能优化题联动起来。第五段是布局与绘制DOM 树和 CSSOM 树合并成渲染树计算布局位置绘制到合成图层上最终在屏幕上显示页面。注意回答这道题不要一条路背到底面试官说“能停一下吗”的时候一定要立刻停下说明你是有意识地输出而不是背诵。这道题最容易出彩的地方是细节补充。比如讲 DNS 解析时提一句“现代浏览器支持 DNS over HTTPSDoH”讲渲染时提一句“首屏优化可以通过提前加载关键 CSS、延迟非关键 JS 来实现”。这些细节不是背诵出来的而是平时项目里真的用到的所以我在准备这道题时从不背标准答案只列主干然后根据面试官的兴趣现场灵活展开。4. 高频核心题精讲框架与工程篇4.1 Vue 2 / Vue 3 响应式原理对比如果你面的是 Vue 技术栈的岗位响应式原理这道题基本躲不掉。我甚至见过一家公司从回答里直接判断候选人的技术深度只答得出 Vue 2 的Object.defineProperty且说不出 Vue 3 的Proxy优势基本会被划到“用过但不够深入”那一档。Vue 2 的响应式核心是Object.defineProperty实现思路是递归遍历数据对象的每个属性用 getter 和 setter 做依赖收集与触发更新。它能拦截已有属性的读写但没有办法拦截新增属性和删除属性所以 Vue 2 才需要Vue.$set、Vue.$delete这些额外 API。数组的响应式更麻烦Vue 2 通过重写push、pop、shift、unshift、splice、sort、reverse七个方法来处理索引赋值和修改 length 仍然无法被拦截。Vue 3 改用Proxy实现响应式核心优势是懒代理和拦截能力更强。Proxy 可以直接代理整个对象包括新增属性、删除属性、读取keys、判断in等操作都能被拦截。配合Reflect保证 this 上下文正确配合effect、track、trigger三个核心函数完成依赖收集与派发更新。还有一个很大的优化是懒代理只有访问到某个属性时才去代理它对应的深层对象初始化性能比 Vue 2 的递归遍历好很多。这题我建议准备一个“从源码角度来看”的回答版本。不要只说“Vue 3 用 Proxy性能更好”要能补充Vue 3 里reactive返回的是一个Proxy代理对象ref内部用Reflect处理了.value的读写computed本质上是一个 lazy effect。如果面试官再追问“Proxy 有什么缺点”可以说兼容性不如Object.definePropertyES6 之后所有现代浏览器支持但老旧浏览器需要 polyfill。4.2 防抖与节流手写实现与使用场景防抖和节流属于“背了不一定会会了不一定写得对”的题。很多人能说出来定义但一到手写就露馅边界条件没处理this 指向错误参数没透传。防抖的核心思想是事件被触发后延迟执行如果在此期间再次触发则重新计时。最适合的场景是搜索框输入联想、窗口 resize 后的重算。手写实现function debounce(fn, delay 300) { let timer null; return function (...args) { if (timer) clearTimeout(timer); timer setTimeout(() { fn.apply(this, args); timer null; }, delay); }; }注意这里fn.apply(this, args)中的this来源于调用时闭包捕获的this箭头函数不会绑定自己的 this所以会继承外层普通函数的 this但这段代码里this其实是在返回的普通函数中获取的应该写成这样。更正一个容易踩的坑如果你在返回函数里用setTimeout(() { ... }.bind(this))或者箭头函数this指向的语义会不同。推荐写法是在返回的普通函数里取到正确的this再用一个普通函数包裹定时回调或者在箭头函数里直接使用外层的this。节流的核心思想是在固定时间窗口内事件只执行一次。最适合的场景是拖动滚动条、鼠标滑动、窗口 resize 的频繁触发。手写实现function throttle(fn, interval 300) { let last 0; return function (...args) { const now Date.now(); if (now - last interval) { last now; fn.apply(this, args); } }; }这个版本简单但不支持 trailing 调用很多面试官会追问“最后一次触发能不能补执行”。进阶版本需要结合定时器在时间差不足时记录最后一次调用待时间窗口结束后再补执行。这块内容多建议自己动手调试一遍比背代码效率高得多。我面试的时候观察到一个现象能写出基础的防抖节流的人不少但能把“为什么需要防抖节流”和“真实项目里哪个功能用了哪个、为什么”讲清楚的人很少。所以我的建议是每道题准备一个真实使用场景比如“我在项目里实现搜索框联想功能输入事件通过防抖延迟 500ms 发送请求避免每敲一个字符都请求接口”。4.3 前端性能优化从指标到实操清单性能优化是面试里最容易聊开的题因为面试官可以通过你的回答快速判断你做过多少真实优化以及你理解性能问题的维度。最理想的是按照“前端性能指标 → 优化手段 → 验证效果”的顺序来回答。先讲指标FCPFirst Contentful Paint、LCPLargest Contentful Paint、CLSCumulative Layout Shift、INPInteraction to Next Paint替代了原来的 FID。再说优化手段加载层面包括资源压缩、CDN 加速、路由懒加载、图片懒加载、字体子集化、HTTP 缓存策略、preload/prefetch 预加载渲染层面包括减少重排重绘、避免长任务阻塞主线程、使用content-visibility、虚拟列表处理大数据量、把计算移出主线程。如果想让回答更有竞争力一定要落到工具链上。我在项目里常用的方式是用 Lighthouse 跑性能基准分用 webpack-bundle-analyzer 分析包体积针对首屏体积最大的依赖做按需加载或 CDN 外部化。例如把一个首屏资源超过 1MB 的页面优化到 300KB 内Lighthouse 分数从 72 提升到 95。这类真实数据比任何概念都有说服力。这道题也很容易用来做反问当你答完一套性能优化方案后可以问面试官“你们团队现在主要关注哪些指标”不仅能展示你对业务的理解还能帮自己判断团队的技术栈和工程成熟度一举两得。5. 面试现场回答八股文的表达技巧与避坑实录5.1 常见答题误区与纠正我在面试别人和帮朋友模拟面试时总结了几个出现频率特别高的答题误区这里逐条分享。第一个误区是只背结论不给推导。比如问“为什么 Vue 3 用 Proxy 替代 Object.defineProperty”有人张口就是“Proxy 性能更好能拦截新增属性”但说不清楚 Proxy 懒代理的原理和Reflect的作用。面试官一听就知道你背过但不是真的理解。纠正方法很简单复习每道题时给自己加一问“为什么”。第二个误区是语速过快像开倍速念稿。很多候选人怕被打断一口气把准备的答案全倒出来。这会带来两个问题一是面试官来不及消化你的信息没法针对性地深入追问反而弱化了你的展示二是容易暴露出“背诵感”失去交流感。建议是每说 3 到 4 句话就停顿一下让面试官有机会插入追问。第三个误区是遇到不会的问题直接答“不会”。八股文的知识点确实很多任何人都有盲区但面试官更在意你面对未知问题时的反应。比如问到一个不熟悉的 API你可以说“这个 API 我平时用得少但根据它的命名和文档我推测它的作用是……如果要在项目里用我会先去查文档确认参数和行为再写个 demo 验证”。这种回答展示了学习能力和思维路径比硬说“不会”好得多。5.2 被追问时的应对策略八股文面试最让人紧张的环节是追问因为很多题目本身是多层嵌套的你以为答完了面试官一句“那你觉得它的实现原理是什么”就把你往下打了一层。我的应对策略是“主干清晰支线诚实”。在回答一道题之前先在脑子里明确这条知识的主干是什么哪些是加分项。比如问 HTTP 缓存主干是强缓存和协商缓存的全流程加分项是内存缓存与磁盘缓存的区别、Cache-Control的优先级、怎么通过 Nginx 配置。回答时先把主干讲完整如果面试官顺着加分项提问你正好展示深度如果面试官打断了表明他对当前层次已经很满意。遇到真不熟悉的追问不要慌。一个实用的技巧是用“以猜代答”的方式推进“我对这个细节没有深入的实践但从整体架构判断它应该是为了解决 xx 问题。如果要验证我可以回去看文档确认。”边说边把话题引到你熟悉的相邻领域上避免直接陷入沉默。千万不要不懂装懂面试官基本都是行家你编编不出来还容易把之前的好印象毁掉。5.3 把八股文讲出项目感的三个套路最后一个想分享的重点如何让“背出来的八股文”听起来像“做过的事情”。这是我在面试中最大的心得也最实用。套路一每个概念配一个真实场景。准备防御时不要只说“减少请求频率”要具体到“我在做城市选择组件时输入关键词会触发地理位置搜索不加防抖的话用户每输入一个字母就会发一次请求接口压力很大。我加了一个 300ms 的防抖并在防抖函数里支持了取消操作避免组件卸载后回调更新状态”。有场景的回答面试官很难怀疑你是背的。套路二主动讲取舍。比如讲到浏览器缓存你可以说“我们的静态资源 CDN 配置了长缓存但业务接口走协商缓存因为接口数据变化频繁强缓存会导致用户看到脏数据。权衡之下长缓存用于版本稳定的静态资源动态接口用 no-cache”。有取舍的回答说明你真的思考过方案选型而不是机械地套用。套路三把面试官引导到你的优势区。如果面试官问到一个你准备不充分的题目你可以先答一个相关的、你熟练的方向然后说“这块我更熟的是 xxx之前我在项目里是这么做的”。比如问到你不太熟的 Webpack 插件开发你可以先简述插件运行原理然后转到“我在项目里主要通过配置和 loader 优化构建速度比如用 thread-loader 多进程编译”。面试官通常愿意顺着你的经验继续聊因为聊你做过的事情比挖掘你没做过的事情更能评估你的实际水平。写在最后前端八股文这东西我一开始也挺排斥觉得它把编程这件事变得像考试。但真正开始认真准备后我发现这些高频题其实是一条很好的知识索引——它逼你把 JavaScript 的执行机制、浏览器的缓存策略、框架的响应式原理这些平时“会用但没细想”的部分重新过一遍。我面试过不少人也带过一些新人见到的技术能力最扎实的那批人恰恰不是背题最多的人而是能在答完一道题之后自然地和你聊原理、聊场景、聊取舍的人。准备面试的时候不妨把每道题当成一次向别人讲清楚一件事的机会而不是一次过关考试。等你真正能把一个概念讲得让别人点头你心里那关也早就过了。