# 自检清单
这一篇的定位是自检与索引,不是题库正文。用法:
- 从上到下扫一遍,能在心里讲清三层追问的打勾,卡住的记下来。
- 每个模块下都标了答案所在的篇目与章节,卡住的题回对应篇目精读。
- 少数在其他篇目里没有独立条目的题,本篇直接给出答案(见「本篇直接作答」)。
说明:本篇过去是一份纯题目清单,没有任何答案。现在每一项都有明确去处——要么指向站内已有的答案章节,要么在本篇末尾直接作答。
# JS
答案位置:基础篇 → JS 基础;进阶篇 → 一、JS 基础;高频篇 → 2 JavaScript;精选篇 → 3 JS 模块 / 4 ES6 模块。手写类看手写篇;算法类看算法篇与排序算法。
- 解释一下原型链 —— 进阶篇「原型与原型链」
instanceof原理 —— 手写篇「手写 instanceof」apply和call的作用及区别 —— 手写篇「手写 call / apply / bind」- 说下你对 DOM 树的理解 —— 高频篇「3 浏览器」
- 实现
add(1)(2)(3)—— 手写篇「函数柯里化相关」 - ES5 实现继承 —— 手写篇「实现类的继承」
- 说下 generator 原理 —— 精选篇 4 ES6 模块
- 实现一个 Promise —— 手写篇「实现 Promise 相关方法」
- 说下事件模型 —— 高频篇「DOM 和事件操作总结」
bind的实现 —— 手写篇「手写 call / apply / bind」- 闭包的作用和原理 —— 进阶篇「闭包」
0.1 + 0.2为什么不等于0.3—— 高频篇「如何判断 0.1 + 0.2 与 0.3 相等」- 前端模块化机制有哪些 —— 进阶篇「模块化」(注意 AMD / CMD 属历史对照,现行主线是 ESM)
- 谈谈变量提升 —— 进阶篇「变量提升与暂时性死区」
new操作符具体做了什么 —— 手写篇「手动实现 new 关键字」- 谈下事件循环机制 —— 高频篇「Event Loop 执行机制过程」
- 谈谈你对作用域的理解 —— 进阶篇「作用域与作用域链」
- V8 垃圾回收机制 —— 精选篇 19 计算机通识 / 高频篇「垃圾回收」
- 合并二维有序数组成一维有序数组 —— 算法篇「排序 / 归并」
- 实现一个
trim方法 —— 手写篇「字符串相关」 - 什么场景下会用策略模式 —— 设计模式篇「策略模式」
- 判断括号字符串是否有效 —— 算法篇「栈」
- 判断链表是否有环 —— 算法篇「链表」
- 爬楼梯问题 —— 算法篇「动态规划」
- 实现一个发布订阅模式 —— 手写篇「手动实现 EventEmitter」
- 实现一个斐波那契数列 —— 算法篇「动态规划」
# CSS
答案位置:基础篇 → CSS;进阶篇 → 三、CSS 基础;高频篇 → 1 CSS;精选篇 → 2 CSS 模块。
- CSS 选择器有哪些 / 优先级怎么计算 —— 高频篇「1 CSS」
- 什么是 BFC,有什么作用,如何形成 —— 高频篇「BFC」
position有哪些值 —— 精选篇 2 CSS 模块- flex 布局有什么好处 —— 精选篇 2 CSS 模块
- 介绍下盒子模型 —— 高频篇「盒模型」
- 有哪些方式可以使 div 居中 —— 精选篇 2 CSS 模块
- CSS 相关的性能优化 —— 精选篇 14 性能优化模块
- 双飞翼 / 圣杯布局 —— 精选篇 2 CSS 模块
- 浮动元素会造成什么影响,如何清除浮动 —— 高频篇「浮动与清除浮动」
- CSS 样式隔离手段 —— 精选篇 2 CSS 模块(另见面经中的微前端样式隔离)
- 行内元素、块级元素有哪些 —— 精选篇 2 CSS 模块
- CSS3 有哪些新特性 —— 精选篇 2 CSS 模块
- 层叠上下文是什么 —— 高频篇「层叠上下文」
- 重排和重绘是什么,有什么区别 —— 高频篇「重绘与回流」
- 动画性能如何优化 —— 精选篇 14 性能优化模块
# React
答案位置:高频篇 → 6 React / 7 React Hooks;进阶篇 → 七、React;精选篇 → 6 React 模块。
React 的行为随版本变化较大,凡是涉及批处理、并发特性、
ref传递的题目,答案都按 React 17 及以前 / React 18 / React 19 三档给出,见高频篇「setState 是同步还是异步(按 React 版本分档)」。
- React 16 新增了哪些生命周期、为什么去掉某些 15 的生命周期 —— 精选篇 6 React 模块(
componentWillMount等在 React 19 已移除,仅UNSAFE_前缀存量可用) react setState是同步还是异步 —— 本篇直接作答(一)- 什么是高阶组件,请举例说明 —— 精选篇 6 React 模块
- React 合成事件是什么,和原生事件的区别 —— 高频篇「React 合成事件原理」
- 为什么有时 React 两次
setState只执行一次 —— 本篇直接作答(二) - Redux 有哪些原则 / 中间件机制 /
compose做什么 / 理念 —— 精选篇 6 React 模块「Redux」 redux-saga和redux-thunk的区别 —— 精选篇 6 React 模块react-redux的connect怎么实现 —— 精选篇 6 React 模块- React 如何处理异常 —— 高频篇「错误边界」(React 19 改为
createRoot的onUncaughtError/onCaughtError选项) - React 为什么需要 Fiber / Fiber 有哪些优点 —— 高频篇「VDOM 与 Fiber」
- mixin、HOC、继承的区别与优缺点 —— 精选篇 6 React 模块
useEffect的实现原理 —— 高频篇「7 React Hooks」- 异步渲染和旧版 diff 的区别 / React diff 如何实现 / 时间复杂度 —— 高频篇「React diff」
- 旧版 diff 用深度优先还是广度优先 —— 高频篇「React diff」
- React 有哪些性能优化的点 —— 精选篇 14 性能优化模块(注意 React Compiler 之后手动
useMemo/useCallback的必要性下降) setState和 Hook 的区别 —— 本篇直接作答(三)react-router实现原理 / hash 与 history 的区别 —— 高频篇「前端路由」- 实现一个
useState—— 手写篇「框架相关」
# Vue
答案位置:高频篇 → 4 Vue2 / 5 Vue3;进阶篇 → 六、Vue;精选篇 → 7 Vue 模块。
Vue 题目答案以 Vue 3 为主线(
Proxy响应式、组合式 API、<script setup>、Pinia),Vue 2 的Object.defineProperty、Vue.set、Vue.mixin作为历史对照。
- Vue 的数据绑定机制是如何实现的 —— 精选篇 7 Vue 模块「响应式数据原理」
- Vue
nextTick实现原理 —— 精选篇 7 Vue 模块「nextTick」 - Vue 的
computed和watch的区别 —— 精选篇 7 Vue 模块「computed 和 watch」 - 说下 Vue 的
keep-alive—— 精选篇 7 Vue 模块「keep-alive 原理」 - Vue / React 技术选型 —— 精选篇 17 框架通识
# 工程化
答案位置:高频篇 → 8 Webpack;进阶篇 → 九、工程化;精选篇 → 9 前端工程模块;Node 相关看 Node 学习指南。
- 是否写过 webpack 插件 / 工作流程 / loader 机制 —— 高频篇「8 Webpack」
- Node 模块机制 /
require具体实现 —— Node 学习指南 - Node 事件循环与浏览器的区别 —— 高频篇「Event Loop(浏览器与 Node 区别)」
- Node 的异常处理方式 —— Node 学习指南
- Tree Shaking 是什么,原理是什么 —— 高频篇「Tree Shaking 原理」
- Babel 是什么 / 转码过程(词法、语法分析) —— 精选篇 9 前端工程模块
- 项目的技术栈怎么选型 —— 面试技巧专栏「技术选型怎么答」与面经中的同名题
# HTTP
答案位置:高频篇 → 9 HTTP;精选篇 → 15 HTTP 模块;系统学习看 HTTP 协议专栏。
- 常用 HTTP 状态码 /
301 302 307区别 / SEO 上哪个更好 —— 精选篇 15 HTTP 模块 - HTTPS 加密过程 / 握手过程 —— HTTP 协议专栏
- HTTP/2 做了哪些改进 / 有哪些不足 / HTTP/3 是什么 —— HTTP 协议专栏
- TCP 三次握手 / 滑动窗口 / 重试机制 —— 精选篇 19 计算机通识
- WebSocket 建立过程 —— 高频篇「WebSocket 握手」
- 简单请求和复杂请求的区别 —— 精选篇 15 HTTP 模块(跨域预检)
# 浏览器
答案位置:高频篇 → 3 浏览器;精选篇 → 5 浏览器模块;系统学习看浏览器原理专栏。
- 浏览器架构 —— 浏览器原理专栏「Chrome 架构」
- 浏览器缓存策略 —— 高频篇「浏览器缓存机制」
- 从输入网址到页面展现的整个过程 —— 浏览器原理专栏
- history 和 hash 两种路由方式的区别 —— 高频篇「前端路由」
- 前端性能优化手段有哪些 / 首页大量图片如何优化 / 如何减少白屏时间 —— 精选篇 14 性能优化模块
- 如何定位内存泄漏 —— 高频篇「内存泄漏检测与场景」
- 跨域是什么、如何解决 / JSONP 有什么缺点 —— 精选篇 15 HTTP 模块
# 综合
答案位置:高频篇 → 11 综合题目;精选篇 → 13 前端安全模块 / 11 小程序模块。
MutationObserver、IntersectionObserver使用场景 —— 精选篇 5 浏览器模块- decorator 的作用,编译后是怎样的 —— 精选篇 4 ES6 模块
- Symbol 是什么,一般用来做什么 —— 精选篇 4 ES6 模块
- 小程序底层实现原理(双线程模型 / 预加载 webview) —— 精选篇 11 小程序模块
- WebSocket 与轮询的好处和缺点 —— 高频篇「WebSocket」
- TCP / UDP 的区别 —— 精选篇 19 计算机通识
# 本篇直接作答
下面三题在其他篇目里没有独立条目,直接在这里给出答案。
# 一、setState 是同步还是异步
先纠正一个流传很广的错误说法:「setState 在 setTimeout 和自定义 DOM 事件里是同步的」——这只在 React 17 及以前成立。
| 版本与根节点 | React 事件 / 生命周期内 | setTimeout / 原生事件 / Promise.then 内 | 强制同步的出口 |
|---|---|---|---|
React 17 及以前(ReactDOM.render) | 批量合并 | 逐次同步刷新 | 本来就是同步的 |
React 18(ReactDOM.render 兼容模式) | 批量合并 | 逐次同步刷新 | 本来就是同步的 |
React 18(createRoot) | 批量合并 | 同样批量合并 | flushSync |
| React 19 | 批量合并 | 批量合并(ReactDOM.render 已移除) | flushSync |
正确的表述是:setState 调用本身是同步的,它把更新入队并请求一次调度;「异步」指的是你读不到刚写入的 state。React 17 及以前靠全局标志 isBatchingUpdates 判断「是否在 React 自己的调用栈里」来决定批处理,所以定时器和原生事件里逃出了批处理、表现得像同步。React 18 起 createRoot 默认 automatic batching,同一个任务内的更新一律合并,unstable_batchedUpdates 不再需要;React 19 移除了 ReactDOM.render,没有退回旧行为的选项。
需要在某一行之后立刻读到已提交的结果时,用 react-dom 的 flushSync 显式退出批处理——它是逃生口,不是常规写法。想在更新提交后做事,类组件用 setState(partial, callback),函数组件用 useEffect 依赖该 state。
完整推导、模拟实现与三档笔试题对照见高频篇「setState 是同步还是异步(按 React 版本分档)」。
# 二、为什么有时 React 两次 setState 只执行一次
这与批处理无关,取决于传对象还是传函数,两个版本都一样:
// 传对象:按 Object.assign 语义合并,后面覆盖前面。
// 两次读到的 this.state.count 都是本轮未更新的旧值,所以连写两次只 +1
this.setState({ count: this.state.count + 1 })
this.setState({ count: this.state.count + 1 })
// 传函数:更新函数排队依次执行,每个都拿到上一个的结果,连写两次真的 +2
this.setState((prev) => ({ count: prev.count + 1 }))
this.setState((prev) => ({ count: prev.count + 1 }))
函数组件完全同理:setCount(count + 1) 对应对象形式的坑,setCount(prev => prev + 1) 对应函数形式。只要新值依赖旧值,就用函数形式。
顺带说清另一个容易混的现象:函数组件里 console.log(count) 永远打印本次渲染的快照,无论怎么写都不会中途变化——这是「state 是渲染快照」导致的,与合并与否是两件独立的事。
# 三、setState 和 Hook(useState)的区别
| 维度 | 类组件 setState | 函数组件 useState |
|---|---|---|
| 更新语义 | 浅合并到现有 state 对象,未提及的 key 保留 | 整体替换,要保留其他字段必须自己展开 setState({ ...state, a: 1 }) |
| 状态粒度 | 一个组件一个 state 对象 | 可以拆成多个独立的 state,按关注点分开 |
| 读取时机 | 读 this.state,读到的是当前实例上的最新已提交值 | 读的是本次渲染的快照,闭包捕获,不会中途变化 |
| 更新后回调 | 有第二个参数 setState(partial, callback) | 没有回调参数,用 useEffect 依赖该 state 代替 |
| 函数式更新 | setState(prev => next) | setCount(prev => next),语义一致 |
| 相等即跳过 | 无此优化,赋相同值也会触发更新流程 | 新值与旧值 Object.is 相等时可能跳过重渲染(但可能仍多渲染一次后停下) |
| 批处理 | 与 useState 完全一致,遵循同一套版本规则 | 同左 |
面试时最容易被追问的两点:「浅合并 vs 整体替换」(这是最实际的差异,迁移时最容易踩),以及**「为什么 useState 没有第二个回调参数」**(因为函数组件没有实例可挂回调,副作用应该由 useEffect 声明式表达,而不是命令式地塞在更新调用里)。
# 模拟题
# 15 道运行题
以下为图片形式的运行结果题,考点集中在类型转换、this 指向、事件循环与作用域。做完对照高频篇「2 JavaScript」与「Event Loop 执行机制过程」自查。

# 20 道简答题
答案位置:1–3、6、17、18、20 见进阶篇「一、JS 基础」;4、11、14 见精选篇 4 ES6 模块;5 见高频篇「事件委托」;7、9、13 见精选篇 15 HTTP 模块;8 见精选篇 13 前端安全模块;10 见高频篇「Event Loop」;12 见精选篇 14 性能优化模块;15 见 Node 学习指南;16 见设计模式篇「观察者与发布订阅」;19 见高频篇「内存泄漏检测与场景」。
- JavaScript 创建对象的几种方式?
- JavaScript 继承的几种实现方式?
- 说一下对
this的理解。 - 什么是
Proxy? - 事件委托是什么?
- 说一下你所理解的闭包。
- 说一下你所理解的 Ajax,如何创建一个 Ajax?(现在应答
fetch为主线,XMLHttpRequest作为历史对照) - 说一下你所理解的同源政策。
- 你是如何解决跨域问题的?
- 你所理解的 JavaScript 事件循环机制是什么?
- 说一下对
Object.defineProperty()的理解。 - 说一下图片的懒加载和预加载。
- 请求服务器数据,GET 和 POST 请求的区别是什么?
Reflect对象创建的目的是什么?require模块引入的查找方式?- 观察者模式和发布订阅模式有什么不同?
- 检查数据类型的方法有几种,分别是什么?
- 谈谈对 JSON 的了解。
- 进行哪些操作会造成内存泄漏?
- 谈谈你所理解的函数式编程。
# 15 道手写题
答案位置:全部见手写篇对应小节(节流防抖、深拷贝、call / apply / bind、柯里化、观察者、EventEmitter、JSONP、new、Object.assign、URL 参数解析、数字格式化、instanceof、数组去重)。
- 实现 JS 的节流和防抖函数,两者的区别是什么?
- 实现 JS 中的深拷贝
- 手写
call函数 - 手写
apply函数 - 手写
bind函数 - 实现柯里化函数
- 手写一个观察者模式
- 手动实现
EventEmitter(发布订阅模式) - 手动实现 JSONP
- 手动实现
new关键字 - 手动实现
Object.assign - 实现解析 URL 参数为对象的函数
- JS 格式化数字(每三位加逗号)
- 手写
instanceof关键字 - 手写数组去重的方法