ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

前端面试高频八股题盘点:50道核心考点与追问死角全解析

前端面试高频八股题盘点:50道核心考点与追问死角全解析 这两年我帮人做模拟面试的次数不少也亲眼见过很多“简历很漂亮、开场很自信”的候选人一到八股环节就崩盘。最典型的画面是闭包背得滚瓜烂熟面试官追问一句“那这个闭包会不会造成内存泄漏”当场卡住new 的原理说得头头是道让手写一个 new写出来的代码连原型都没挂上。前端面试最常考、最容易被问崩的 50 道八股题恰恰就藏在“背得会”和“讲得清”之间的那层落差里。这篇文章不打算让你死记硬背更不是直接把 50 道题的答案甩出来就完事。我会把这 50 道高频题按类别盘点清楚标出每道题最常见的追问方向再挑几类“问崩率”最高的题做深度拆解最后给一套可以直接用的答题框架。无论你是准备春招秋招的应届生还是有 1-3 年经验想跳槽的前端都可以照着这份清单去自查复习。1. 背完八股还是被问崩真正的考点从来不是答案1.1 面试官到底想通过八股听到什么八股题表面上是在考定义本质上考的是两件事你知不知道这个知识点以及你能不能把它的运作机制讲清楚。我当面试官的时候听一个人讲“闭包”最想确认的不是他能背出“函数嵌套函数、内层函数能访问外层变量”这句话而是他脑子里有没有“作用域链”和“变量对象”这些底层概念。你会发现常考八股可以粗略分成两类。一类是“概念型”比如“盒模型是什么”这类题背定义基本够用另一类是“机制型”比如“事件循环怎么执行”“new 的时候发生了什么”这类题只背结论面试官一个追问就把你打回原形。前端面试里最容易问崩的题绝大多数属于机制型因为它们天然连着源码、手写题和边界场景。同一个知识点面试官至少有三种问法。以 new 为例直接问“new 做了什么”这是背结论让你“手写一个 new”这是考实现细节再追问“箭头函数能不能 new为什么”“构造函数 return 了一个对象会怎样”这就是在考察你对 JS 语言机制的边界意识。这三种问法对应的不是同一个难度层级你备考阶段就要把这些变形提前过一遍。1.2 三种最容易崩的答法我在模拟面试里总结了三种高发“崩法”你可以对照一下自己有没有踩中。第一种只背结论不给过程。比如“虚拟 DOM 一定比真实 DOM 快吗”标准答案是“不一定”但很多人一上来就说“虚拟 DOM 快因为它减少了 DOM 操作”。这个回答连第一层追问都挡不住那为什么 Vue、React 不直接用真实 DOM 做局部更新第二种概念能默写但讲不清“为什么这样设计”。例如“前端为什么要模块化”大部分人都能说出“方便维护、方便复用”可面试官真正想听的是作用域隔离怎么解决变量污染、依赖关系如何管理、打包产物为什么需要 tree-shaking。这三个层次是说不出“复用”两个字就打发的。第三种无法消化追问。八股的追问链通常是两层甚至三层从触发条件问到实现机制再从实现机制问到异常场景。比如“HTTP 缓存”你先讲强缓存、协商缓存是不够的面试官会继续问“地址栏回车、普通刷新、强制刷新缓存表现分别是什么”这一下就能筛掉一大半人。所以备考八股的第一原则不是“背全”而是“给每道题准备好第二层、第三层答案”。接下来的全景清单我会直接把追问方向标出来你复习时照着这个维度去补。2. 50 道高频八股全景清单考点分级与问法变形2.1 50 道题全景表这一节我把最常考的 50 道题按类别整理成了一张表每一行同时标注了“常见追问/变形”。它可以直接当复习索引用你也可以把不会的题圈出来逐个去补原理。序号类别常考题目常见追问 / 变形1JS 核心闭包是什么 应用场景内存泄漏for 循环 var 问题2JS 核心原型链与继承的实现方式手写 ES5 继承class 继承怎么实现3JS 核心this 指向的判断规则箭头函数 this如何显式修改 this4JS 核心call / apply / bind 的区别手写 bindbind 之后的函数还能 new 吗5JS 核心new 的执行过程手写 new构造函数返回对象会怎样6JS 核心深拷贝与浅拷贝手写深拷贝循环引用JSON 拷贝为什么失效7JS 核心防抖与节流手写实现分别适合什么场景8JS 核心Promise 基础手写 Promise.all / race链式调用原理9JS 核心async/await 与 Promise 的关系await 后面的代码什么时候执行10JS 核心事件循环宏任务与微任务给段代码说输出顺序定时器是宏任务吗11JS 核心变量提升与暂时性死区let / const / var 区别函数声明优先级12JS 核心 与 及类型转换[] ![] 为什么是 true13JS 核心typeof 与 instanceof如何准确判断数组Object.prototype.toString 原理14JS 核心数组去重与常用高阶函数手写去重filter / map / reduce 各自用途15JS 核心函数柯里化手写 curry实际应用场景16JS 核心垃圾回收机制V8 分代回收常见内存泄漏场景17JS 核心迭代器与生成器手写可迭代对象Generator 的用途18浏览器与网络浏览器缓存机制强缓存和协商缓存字段刷新按钮影响19浏览器与网络输入 URL 到页面渲染全过程script 阻塞defer 与 async 区别20浏览器与网络HTTP 状态码语义301 / 302 / 304 / 401 / 403 场景21浏览器与网络TCP 三次握手与四次挥手为什么握手 3 次、挥手 4 次22浏览器与网络HTTPS 握手过程对称加密与非对称加密如何配合23浏览器与网络跨域原因与解决思路CORS 预检请求触发条件24浏览器与网络Cookie 与 Web Storage 区别Cookie 如何被 CSRF 利用25浏览器与网络XSS 攻击类型与防御存储型 XSS 怎么发生CSP 有什么用26浏览器与网络CSRF 攻击原理与防御为什么加 token 就能防SameSite 属性27浏览器与网络事件冒泡 / 捕获 / 事件委托手写事件委托stopPropagation 与 preventDefault28浏览器与网络重排与重绘哪些属性触发重排如何合并优化29CSS 与页面盒模型与 box-sizingcontent-box 与 border-box 宽度如何计算30CSS 与页面BFC 与触发条件overflow 清浮动的原理31CSS 与页面Flex 布局核心属性flex: 1 是什么的简写剩余空间分配规则32CSS 与页面Grid 布局与 Flex 取舍二维布局场景怎么选33CSS 与页面水平垂直居中方案不定宽高怎么做flex / grid / absolute 区别34CSS 与页面层叠上下文与 z-indexz-index 相同时谁在上嵌套层叠上下文35CSS 与页面选择器优先级计算1000 个 class 能和 ID 比吗36框架与工程化虚拟 DOM 一定比真实 DOM 快吗diff 算法怎么优化为什么跨平台37框架与工程化key 的作用与 diff 算法key 用 index 会有什么问题38框架与工程化Vue 响应式原理Vue2 与 Vue3 差异为什么用 Proxy39框架与工程化React setState 同步还是异步更新如何合并为什么 setTimeout 内变同步40框架与工程化组件间通信方式父子 / 兄弟 / 跨层级怎么传41框架与工程化路由实现原理hash 路由与 history 路由差异42框架与工程化useEffect 与生命周期对应关系依赖数组为空还执行几次闭包陷阱43框架与工程化CommonJS 与 ES Module 区别require 为什么能动态加载import 为什么静态44框架与工程化Webpack 构建流程loader 和 plugin 的区别45框架与工程化Vite 为什么比 Webpack 快开发依赖预构建ESM 按需加载46框架与工程化Tree Shaking 原理为什么必须 ES Module副作用标记47框架与工程化大文件上传方案分片、断点续传、秒传怎么设计48框架与工程化Web Worker 与多线程主线程如何通信结构化克隆49框架与工程化React Hooks 原理为什么不能写在条件语句里50框架与工程化前端模块化演进AMD / CMD / CommonJS / ESM 差异2.2 按梯队分配复习权重50 道题不可能平均用力我建议你按三个梯队分配时间。第一梯队是“几乎每场必考”事件循环、闭包与内存、原型链与继承、new 的过程、HTTP 缓存、输入 URL 全过程、虚拟 DOM 与 key、Vue/React 的更新机制、组件通信。这些题不依赖具体业务场景面试官最喜欢在开场基本功环节连问三轮而且最容易从概念滑向手写。第二梯队“出现概率高且常结合项目追问”深拷贝、防抖节流、跨域、重排重绘、模块化、构建流程、路由原理、React Hooks 原则。这类题往往和候选人简历上的项目绑定比如你写了上传功能面试官顺手就问你大文件分片怎么做实际考的还是 Worker 和文件操作的基础。第三梯队“看岗位方向取舍”CSS 细节题、Canvas 与可视化、微前端、Tree Shaking、迭代器与生成器。投可视化方向就把 Canvas 相关补足投基建方向就把 Webpack/Vite 往深挖别盲目平均用力。3. JS 专题闭包、new、事件循环的追问死角3.1 闭包题答出内存模型才算过关闭包是最经典的前端八股也是问崩率最高的一道题。原因是大多数人只背了“函数嵌套函数内层函数能访问外层变量”这句话却连闭包为什么能访问外层变量都没想明白。正确的展开方式应该是这样的每个函数在定义时会创建自己的执行上下文内部函数除了自己的活动变量对象还会把外层函数的活动变量对象留在自己的作用域链上。当外层函数执行结束正常情况下它的作用域对象会被释放但因为内层函数仍然保持着引用这个变量对象就不会被回收于是内层函数即使在外部被调用仍然能读取到那些变量。这就是闭包的本质内部函数持有对外层作用域的引用形成了作用域的快照。应用场景要能现场举两个。一个是函数柯里化一个是防抖节流。以防抖为例function debounce(fn, delay) { let timer null; return function (...args) { if (timer) clearTimeout(timer); timer setTimeout(() { fn.apply(this, args); }, delay); }; }这里的 timer 就是闭包变量每次调用返回函数时复用的是同一个定时器 id。这种代码面试官不仅让你写还会让你解释“为什么 timer 不会被重置”——答案正是因为闭包维持了对 timer 的引用。追问里还有一个高频点内存泄漏。闭包本身不一定会泄漏但如果内部函数长期存活并且引用了大型对象、DOM 节点那这些数据就无法被回收。经典题是 for 循环里的 varfor (var i 0; i 5; i) { setTimeout(() console.log(i), 0); } // 输出 5 5 5 5 5原因是 setTimeout 的回调函数都共享同一个外层作用域里的 i。改用 let 之后每次循环都会创建独立绑定这是词法环境层面的差异而不是“let 有块级作用域”一句话就能含糊带过的。3.2 new 到底发生了什么手写和原理一起考“说说 new 一个对象的过程中发生了什么”是我眼里被低估的高频题因为它可以无缝衔接手写题。标准过程分四步创建一个新对象把它的原型指向构造函数的 prototype。把构造函数的 this 绑定到新对象上。执行构造函数内部的代码给新对象添加属性和方法。如果构造函数返回了引用类型就直接返回那个引用类型否则返回第一步创建的新对象。手写实现通常是这样的function myNew(Constructor, ...args) { const obj Object.create(Constructor.prototype); const result Constructor.apply(obj, args); return result ! null (typeof result object || typeof result function) ? result : obj; }关键是第四步的判断。很多人写完前两步就停了漏掉“构造函数返回对象时要覆盖新对象”这个分支。面试官往往就在这里设伏如果构造函数 return 了一个普通对象new 的结果是那个对象而不是 this如果 return 的是基本类型则会被忽略仍然返回新建对象。另一个高频追问箭头函数能不能 new答案是不能。因为箭头函数没有自己的 this也没有 prototypenew 的第一步就要把新对象的原型挂到构造函数的 prototype 上这条路根本走不通。3.3 事件循环题宏任务微任务的坑事件循环几乎是前端面试的“必杀题”因为它可以一题串起异步、性能、浏览器机制。最基础的题是判断输出顺序console.log(script start); setTimeout(() console.log(timer), 0); Promise.resolve().then(() console.log(promise)); console.log(script end); // 输出script start / script end / promise / timer理解口径是这样JS 引擎执行完当前脚本后先处理微任务队列再取一个宏任务执行。Promise.then 进微任务队列setTimeout 回调进宏任务队列所以微任务先执行。这个基础版本大部分人能答对真正容易崩的是加了 async/await 的变形async function test() { console.log(1); await Promise.resolve(); console.log(2); } test(); console.log(3); // 输出1 / 3 / 2原因在于 await 会把后面的代码编译成类似“.then”的回调放入微任务队列。所以 console.log(2) 不会立刻执行而是等当前同步代码跑完、微任务阶段到来后才输出。如果你能把这个脱糖过程讲明白面试官就很难再在这个点上把你问崩。4. 浏览器网络专题从输入 URL 到缓存到跨域4.1 输入 URL 到页面渲染一条线考完多轮“从输入 URL 到页面渲染浏览器做了什么”是所有网络类八股的母题因为它可以拆出一整条追问链。我的建议是把它按阶段背熟每个阶段后面挂一个预备追问。阶段拆解如下URL 解析判断输入是否合法、是否有协议头。DNS 解析将域名解析为 IP本地会优先查浏览器缓存、OS 缓存、路由器缓存。TCP 连接三次握手建立连接HTTPS 时还要进行 TLS 握手协商加密密钥。发送 HTTP 请求携带请求头、Cookie 等服务器返回 HTML 文档。解析 HTML 构建 DOM 树解析 CSS 构建 CSSOM 树。合成渲染树执行布局Layout、绘制Paint、合成Composite。加载外部资源JS 的执行会阻塞解析所以有 defer / async 来改变执行时机。每一步都能牵出一个子问题。比如“JS 为什么要阻塞解析”因为 JS 可能通过 document.write 改写 DOM 结构浏览器必须先执行完 JS 才能确定后续文档结构。再比如“CSS 放在 head 里、JS 放在 body 底部”的原因CSS 不阻塞 DOM 解析但会阻塞渲染要尽早拿到JS 放在底部是为了避免阻塞初始渲染。我见过好多人在这个环节掉链子是因为他们只背了“构建 DOM、构建 CSSOM、生成渲染树”却不知道浏览器还有预加载扫描、资源加载优先级这些机制。你不一定每条都答全但至少要能按顺序流畅讲完主干再承认“更细的资源调度机制我了解一部分”给自己留出缓冲空间。提示背这条链路时最好和 HTTP 缓存连起来记。“index.html 走协商缓存静态资源走强缓存”这个实际场景能把两个知识点串成一个体系。4.2 HTTP 缓存强缓存与协商缓存刷新操作是加分区分点HTTP 缓存题最大的区分点在“能否讲清强缓存和协商缓存的完整流程”。维度强缓存协商缓存核心字段Cache-Controlmax-age、ExpiresETag、Last-Modified命中表现不发请求直接读本地缓存发请求给服务器确认返回 304 则用缓存判断方式本地过期时间是否有效服务器对比资源标识是否变化优先级Cache-Control 高于 ExpiresETag 高于 Last-Modified强缓存的核心是 Cache-Control用的计算逻辑是“请求时间 max-age 当前时间”。超过这个时间就进入协商缓存阶段带上 If-None-Match 或 If-Modified-Since让服务器判断资源有没有变化没变化就返回 304。很多人背到这里就停了其实面试官真正爱问的是刷新操作的区别。地址栏回车浏览器会正常走缓存策略普通刷新F5页面会重新请求一般会带上 If-Modified-Since / If-None-Match 去做协商强制刷新CtrlF5浏览器通常会把请求头里的缓存字段清掉直接向服务器拿最新资源。实际开发里改完前端代码后线上还是旧版本很多新人对“为什么强缓存没有失效”一脸茫然就是这里没想透。4.3 跨域为什么预检请求容易被忽略跨域题的崩点主要有两个一是说不清“为什么浏览器要限制跨域”二是把 CORS 简单得只回答“服务器加个 Access-Control-Allow-Origin 就行”。先说限制原因浏览器同源策略保护的是用户数据在用户已登录站点 A 的情况下如果恶意站点 B 可以任意发起跨域请求用户的认证信息就会被悄悄带走这是 CSRF 的核心风险。所以浏览器默认只允许同源请求跨域请求要由服务端显式声明允许。难点在预检请求。不是所有跨域请求都会触发预检只有使用了 GET/HEAD/POST 之外的方法如 PUT、DELETE或者设置了非简单请求头或者 Content-Type 不属于 text/plain、multipart/form-data、application/x-www-form-urlencoded 时浏览器才会先发一个 OPTIONS 请求询问服务器允许哪些方法和头得到回应后才会发起真实请求。这个细节在实际接口联调时特别常见尤其是自定义 header 的场景。老项目里还会遇到 JSONP。它的原理是利用 script 标签不受同源策略限制让服务器返回一段调用全局回调函数的 JS 代码。但它只能发 GET 请求且有脚本注入风险现在主要用来兜底老接口。5. 框架专题虚拟 DOM、key、响应式的三座大山5.1 虚拟 DOM 一定更快吗最常见的误区这道题几乎是框架类八股的第一道送命题因为“虚拟 DOM 比真实 DOM 快”这句话在圈子里流传太广以至于很多人把“有争议的结论”当成“标准答案”来背。真实答案是虚拟 DOM 不一定更快。真实 DOM 操作本身并不慢慢的是频繁操作引发的布局抖动和重排重绘。虚拟 DOM 的价值是通过 JS 层面的 diff 计算出最小变更集再把变更批处理地应用到真实 DOM从而减少无谓的渲染开销。它的核心收益是“可控”而不是“绝对更快”。此外虚拟 DOM 还带来两个很容易被忽略的好处。一是跨平台能力因为渲染目标是抽象的只要提供不同的渲染器就能把同一套组件渲染到 DOM、Canvas、原生 App 甚至测试环境。二是开发体验开发者从命令式“找节点、改属性”变成声明式“数据变了界面自动跟着变”心智负担大幅下降。追问通常会落在 diff 算法上。最原始的树 diff 需要遍历两棵树的节点组合复杂度是 O(n^3)React/Vue 通过三条策略优化到 O(n)只看同层节点不同类型节点直接重建通过 key 判断同一层节点是否可复用。讲出这三条你就能在同届候选人里拉开差距。5.2 key 的作用从 diff 细节到真实案例key 是 diff 优化的关键也是面试官很爱深入追问的点。key 的作用是给节点一个唯一标识让 diff 在比对同一层子节点时能判断两个节点是否是同一个对象从而决定“移动、复用”还是“删除、重建”。高频崩点是“key 用 index 有什么问题”。我用一个简单例子说明{list.map((item, index) ( Item key{index} data{item} / ))}当列表顺序变化、中间插入一条数据或者删除一条数据时index 会跟着变diff 就误判为“原来的节点被删了来了一个新节点”于是原本不需要重建的组件被迫卸载重建。如果一个组件内部有输入框或者维持着展开状态这些 UI 状态就会错乱。所以列表项的 key 尽量用唯一且稳定的 id而不是随机值也不是索引。追问到这里你还可以主动补一句如果列表项有拖拽排序移动之后组件位置变化稳定的 key 能让 diff 识别成“移动节点”而不是“删除重建”这也是为什么虚拟列表、antd Table 这类组件特别强调 key 的稳定性。5.3 Vue 响应式 vs React 更新机制八股里的对比题Vue 和 React 的更新机制是框架题里最有“对比色彩”的一类。面试官想看的不是你会不会背 API而是两种范式你真的理解了多少。Vue2 的响应式基于 Object.defineProperty递归遍历 data 的每个属性重写 getter/setter在首次渲染时收集依赖数据变化时触发更新。它的代价有三个无法监听新增和删除属性需要额外 $set / $delete对数组索引和 length 的监听不可靠所以 Vue2 重写了数组的 push、pop、splice 等方法初始化时递归遍历成本高。Vue3 改用 Proxy可以直接拦截对象属性的新增、删除、读写对数组也能原生监听还能按需惰性代理这正是 Proxy 在响应式体系里取代 defineProperty 的根本原因。React 则是另一套思路。它的更新核心是“不可变数据 setState 触发调和”。每次数据变化React 会重新执行 render 函数生成新的虚拟 DOM再做 diff。因为状态是不可变的React 才能确定地知道“旧树没被外部修改”diff 的结果才可信。setState 本身是异步批量处理的同一个事件循环里的多次 setState 会被合并这是为了减少重复渲染。这两套方案没有绝对优劣Vue 的依赖收集更精确更新粒度小React 的不可变数据流更利于时间旅行调试和复用逻辑。你备考时最好把自己主用框架的原理和另一套框架做个对照一旦面试官问“为什么 React 不自动更新”你就能从“不可变值”和“可变代理”的差异去回答。6. 拆题式答题模板与考前避险清单6.1 四步答题模板定义、原理、代码、追问我总结了一个能覆盖大部分八股题的四步答法一句话定义 → 原理拆解 → 代码或案例 → 主动补边界。这个模板可以让你在紧张状态下至少保持结构清晰。用“防抖与节流”举个例子。第一步一句话定义防抖是连续触发中只让最后一次生效节流是固定时间间隔内最多执行一次。第二步原理拆解防抖靠 setTimeout 不断重置定时器每次触发都清除上一个节流靠时间戳或定时器保证执行频率不高于阈值。两者都是闭包的典型应用通过闭包维护定时器状态。第三步给出代码防抖代码直接写出来顺带说一句为什么用 apply 修正 this。第四步主动补边界防抖适合搜索框输入、按钮连点节流适合滚动事件、resize 事件。实际使用还需要考虑是否需要立即执行版本、取消取消防抖的方法。你只要主动说出这些面试官就很难再往下砸你不准备的角落。这套模板的核心逻辑是不要等面试官一层层问而是你自己把知识的边界主动暴露出来。你把边界说完了提问空间就被你压缩了。6.2 考前避险自查清单最后分享一份我给自己和身边朋友用的考前自查清单建议你面试前一晚过一遍。对 50 道题里的每一道能不能用“一句话定义 三步讲清”的方式讲给自己听每道题旁边是否标了至少两个追问方向追问方向有没有准备“为什么”层面的答案高频手写题从头写过三遍以上吗new、深拷贝、防抖节流、Promise.all、bind这四道建议闭眼默写。能不能把某个八股知识点和你简历里的项目场景对应起来比如你做过上传就一定要能聊大文件分片。有没有做完至少三轮模拟面试最好是录音复盘听自己回答问题时的语气和逻辑。我的个人经验是八股复习最忌讳贪多求全。把 50 道核心题的“为什么链条”理清楚比稀里糊涂刷 200 道题有用得多。尤其到了面试现场你的目标是让面试官觉得“这个人基础扎实而且是真的理解”而不是“这个人背题很熟但没写过几行代码”。前端面试常考的核心题就那么多真正拉分的往往不是你知道多少而是你能在压力下把一条链路讲得多完整。希望这份清单能帮你把最容易崩的环节提前补上下次面试别再栽在闭包和 key 上。
返回列表