一、JavaScript 核心:闭包、原型链与异步编程
高频问题
- “闭包的常见使用场景是什么?滥用会导致什么问题?”
- “如何实现一个
new运算符?手动实现时有哪些细节需要注意?” - “
Promise.then的链式调用中,错误处理如何逐层传递?”
避坑要点
-
闭包的内存泄漏“隐形杀手”
- 经典错误:在循环中创建闭包,误用变量(如用
var导致变量污染)。 - 代码示例:
for (var i = 0; i < 5; i++) { setTimeout(() => console.log(i), 100); // 输出 5 个 5 } // 修复方案:改用 let 或 IIFE 隔离作用域 - 进阶考点:如何用
WeakMap管理闭包引用,避免内存泄漏。
- 经典错误:在循环中创建闭包,误用变量(如用
-
原型链的“隐藏坑”
- 面试题:
function Person() {} Person.prototype = { name: "Alice" }; const p = new Person(); console.log(p.constructor === Person); // false! - 避坑解析:手动覆盖
prototype会破坏constructor指向,需显式修复:Person.prototype = { constructor: Person, // 修复构造函数指向 name: "Alice" };
- 面试题:
-
异步编程的“执行顺序陷阱”
- 代码分析:
console.log(1); setTimeout(() => console.log(2), 0); Promise.resolve().then(() => console.log(3)); console.log(4); - 正确顺序:
1 → 4 → 3 → 2 - 避坑总结:牢记 微任务(Promise)优先于宏任务(setTimeout)。
- 代码分析:
二、React 原理:Fiber、Hooks 与性能优化
高频问题
- “React 的 Diff 算法中,
key的作用是什么?为什么不能用索引?” - “
useEffect的清理函数(cleanup)在什么时机执行?” - “如何用 React.memo 优化组件渲染?什么场景下会失效?”
避坑要点
-
Fiber 架构的“时间切片”误解
- 错误回答:“Fiber 是为了让 React 支持多线程”。
- 正确解析:
- Fiber 是可中断的链表结构,实现任务分片与优先级调度。
- 核心目标:避免长时间任务阻塞主线程(如渲染大量数据时)。
-
Hooks 依赖数组的“深度依赖”问题
- 陷阱代码:
useEffect(() => { fetchData({ page: 1, size: 10 }); }, [props.filter]); // 对象类型依赖,易引发无限循环 - 修复方案:
- 使用
useMemo缓存对象:const params = useMemo(() => ({ page: 1 }), []); - 改用原始类型依赖:
[props.filter.type]。
- 使用
- 陷阱代码:
-
性能优化的“过度 Memo”反模式
- 错误实践:对所有组件无脑包裹
React.memo。 - 正确策略:
- 仅对渲染成本高且 props 变化少的组件使用 Memo。
- 结合
useCallback避免函数引用变化。
- 错误实践:对所有组件无脑包裹
三、浏览器原理:渲染机制、缓存与安全
高频问题
- “从输入 URL 到页面渲染,详细说明浏览器做了什么?”
- “强缓存与协商缓存的优先级如何?
Cache-Control的no-cache和no-store区别?” - “如何防御 XSS 攻击?
innerHTML有哪些安全隐患?”
避坑要点
-
渲染流程的“重排风暴”
- 错误代码:
for (let i = 0; i < 100; i++) { element.style.width = i + "px"; // 触发 100 次重排! } - 优化方案:
- 使用
requestAnimationFrame批量更新。 - 读写分离(先读取
offsetHeight,再统一修改样式)。
- 使用
- 错误代码:
-
缓存策略的“配置矛盾”
- 错误配置:同时设置
Cache-Control: max-age=3600和no-cache。 - 正确逻辑:
max-age=3600:资源在 1 小时内强制使用缓存,不请求服务器。no-cache:每次需验证缓存有效性(向服务器发送请求)。
- 错误配置:同时设置
-
XSS 防御的“转义盲区”
- 危险操作:直接渲染用户输入的富文本(如评论内容)。
- 安全方案:
- 使用
DOMPurify库对 HTML 进行过滤。 - 避免将用户输入直接插入
script标签或事件处理器(如onclick="<%= userInput %>")。
- 使用
四、CSS 布局:Flex、Grid 与响应式设计
高频问题
- “Flex 布局中,
flex: 1的具体含义是什么?” - “如何实现一个左侧固定宽度、右侧自适应的两栏布局?”
- “
position: sticky的生效条件是什么?”
避坑要点
-
Flex 的“缩写属性误解”
flex: 1的真相:等价于flex: 1 1 0%(放大比例、收缩比例、基准值)。- 常见错误:误认为
flex: 1的基准值是剩余空间(实际为 0,按比例分配)。
-
Grid 布局的“隐式网格陷阱”
- 代码示例:
.container { display: grid; grid-template-columns: repeat(2, 100px); } /* 子项超过 2 列时,浏览器自动创建隐式列(宽度由内容决定) */ - 可控方案:显式定义
grid-auto-columns: 50px;约束隐式列。
- 代码示例:
-
响应式设计的“像素完美误区”
- 错误实践:为每个断点编写大量固定像素值。
- 推荐方案:
- 使用
clamp()函数实现流体尺寸:width: clamp(300px, 50vw, 600px); - 结合
minmax()创建自适应 Grid 布局。
- 使用
五、算法与数据结构:前端向高频题
高频问题
- “手写一个深拷贝函数,处理循环引用和特殊对象(如 Date、RegExp)。”
- “实现一个 LRU 缓存机制。”
- “二叉树层序遍历的迭代实现。”
避坑要点
-
深拷贝的“循环引用黑洞”
- 错误代码:未处理循环引用导致栈溢出。
- 修复方案:使用
WeakMap缓存已拷贝对象:function deepClone(obj, cache = new WeakMap()) { if (obj === null) return null; if (cache.has(obj)) return cache.get(obj); // ...处理其他类型 }
-
LRU 缓存的“时间复杂度陷阱”
- 错误实现:用数组维护访问顺序(查找复杂度 O(n))。
- 高效方案:结合
Map的插入顺序特性(ES6+):class LRUCache { constructor(capacity) { this.cache = new Map(); this.capacity = capacity; } get(key) { if (!this.cache.has(key)) return -1; const value = this.cache.get(key); this.cache.delete(key); this.cache.set(key, value); // 更新访问顺序 return value; } }
六、工程化:Webpack 优化与 Babel 配置
高频问题
- “Webpack 的 Tree Shaking 为什么失效?如何排查?”
- “Babel 的
preset-env中useBuiltIns: 'usage'的作用是什么?” - “如何优化 Webpack 构建速度?”
避坑要点
-
Tree Shaking 的“副作用干扰”
- 失效场景:模块被标记为有副作用(如
package.json中"sideEffects": true)。 - 修复方案:
- 显式声明无副作用文件:
"sideEffects": ["*.css"] - 在代码中标注
/*#__PURE__*/(标记无副作用函数)。
- 显式声明无副作用文件:
- 失效场景:模块被标记为有副作用(如
-
Babel 配置的“冗余 polyfill”
- 错误配置:同时使用
@babel/preset-env和@babel/polyfill(导致重复引入)。 - 正确方案:
- 设置
useBuiltIns: 'usage'按需加载 polyfill。 - 在
browserslist中定义目标浏览器范围。
- 设置
- 错误配置:同时使用
-
Webpack 构建的“慢如蜗牛”
- 加速技巧:
- 使用
cache-loader或hard-source-webpack-plugin缓存构建结果。 - 并行处理:
thread-loader或HappyPack(Webpack 4)。
- 使用
- 加速技巧:
七、网络协议:HTTP/2、WebSocket 与性能优化
高频问题
- “HTTP/2 的多路复用(Multiplexing)解决了什么问题?”
- “WebSocket 如何实现心跳机制?”
- “TCP 的拥塞控制算法有哪些阶段?”
避坑要点
-
HTTP/2 的“队头阻塞”误解
- 错误认知:“HTTP/2 完全解决了队头阻塞”。
- 真相:HTTP/2 在应用层解决了队头阻塞(一个 TCP 连接多路复用),但 TCP 层的队头阻塞依然存在。
-
WebSocket 心跳的“保活逻辑”
- 代码示例:
const ws = new WebSocket("wss://api.example.com"); let timer = setInterval(() => { ws.send(JSON.stringify({ type: "ping" })); // 发送心跳 }, 30000); ws.onclose = () => clearInterval(timer); - 避坑提醒:需处理心跳超时与重连机制。
- 代码示例:
八、开放题:项目设计与系统设计
高频问题
- “如果让你设计一个前端监控系统,你会关注哪些指标?”
- “如何实现一个支持撤销/重做的富文本编辑器?”
避坑要点
- 系统设计的“假大空”回答
- 错误示范:只提“使用 React + Node.js”,无具体模块设计。
- 加分回答:
- 前端监控系统:
- 数据采集:错误日志、性能指标(FP/FCP)、用户行为。
- 数据传输:Web Worker 异步上报、抽样策略。
- 数据存储:分库存储(错误日志 vs 性能数据)。
- 撤销/重做功能:
- 数据模型:使用命令模式(Command Pattern)记录操作快照。
- 性能优化:限制历史记录栈深度(如最多 100 步)。
- 前端监控系统:
🔍 如何彻底掌握这些考点?
本文所有题目均来自刷题工具前端面试题宝典 (点我)的「大厂真题库」,提供:
- ✅ 1600+ 真题分类训练:JavaScript、React、算法、系统设计等 22 个方向
- ✅ 大厂前端校对:每道题经过大厂前端老师校对,保证准确性
- ✅ 专项复习:除了按技术栈刷题,还可以根据知识点进行刷题,不仅有前端知识点介绍,还可关联相关面试题
- ✅ 答题要点:每道面试题都有答题要点总结,不用死记硬背,轻松掌握答题技巧~
总结
前端面试的核心逻辑:“深度优先,广度兼备”。
- 深度:对核心原理(如事件循环、Fiber 架构)的理解需直达本质。
- 广度:对工程化、网络、安全等方向的考察逐年增加。
通过 全网特别全的刷题工具 的系统刷题,可快速定位知识盲区,掌握“避坑”方法论。刷题不是目的,建立完整的知识体系才是关键!