# 自检清单

这一篇的定位是自检与索引,不是题库正文。用法:

  1. 从上到下扫一遍,能在心里讲清三层追问的打勾,卡住的记下来。
  2. 每个模块下都标了答案所在的篇目与章节,卡住的题回对应篇目精读。
  3. 少数在其他篇目里没有独立条目的题,本篇直接给出答案(见「本篇直接作答」)。

说明:本篇过去是一份纯题目清单,没有任何答案。现在每一项都有明确去处——要么指向站内已有的答案章节,要么在本篇末尾直接作答。

# JS

答案位置:基础篇 → JS 基础;进阶篇 → 一、JS 基础;高频篇 → 2 JavaScript;精选篇 → 3 JS 模块 / 4 ES6 模块。手写类看手写篇;算法类看算法篇与排序算法。

  • 解释一下原型链 —— 进阶篇「原型与原型链」
  • instanceof 原理 —— 手写篇「手写 instanceof」
  • applycall 的作用及区别 —— 手写篇「手写 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-sagaredux-thunk 的区别 —— 精选篇 6 React 模块
  • react-reduxconnect 怎么实现 —— 精选篇 6 React 模块
  • React 如何处理异常 —— 高频篇「错误边界」(React 19 改为 createRootonUncaughtError / 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.definePropertyVue.setVue.mixin 作为历史对照。

  • Vue 的数据绑定机制是如何实现的 —— 精选篇 7 Vue 模块「响应式数据原理」
  • Vue nextTick 实现原理 —— 精选篇 7 Vue 模块「nextTick」
  • Vue 的 computedwatch 的区别 —— 精选篇 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 小程序模块。

  • MutationObserverIntersectionObserver 使用场景 —— 精选篇 5 浏览器模块
  • decorator 的作用,编译后是怎样的 —— 精选篇 4 ES6 模块
  • Symbol 是什么,一般用来做什么 —— 精选篇 4 ES6 模块
  • 小程序底层实现原理(双线程模型 / 预加载 webview) —— 精选篇 11 小程序模块
  • WebSocket 与轮询的好处和缺点 —— 高频篇「WebSocket」
  • TCP / UDP 的区别 —— 精选篇 19 计算机通识

# 本篇直接作答

下面三题在其他篇目里没有独立条目,直接在这里给出答案。

# 一、setState 是同步还是异步

先纠正一个流传很广的错误说法:「setStatesetTimeout 和自定义 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-domflushSync 显式退出批处理——它是逃生口,不是常规写法。想在更新提交后做事,类组件用 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 见高频篇「内存泄漏检测与场景」。

  1. JavaScript 创建对象的几种方式?
  2. JavaScript 继承的几种实现方式?
  3. 说一下对 this 的理解。
  4. 什么是 Proxy
  5. 事件委托是什么?
  6. 说一下你所理解的闭包。
  7. 说一下你所理解的 Ajax,如何创建一个 Ajax?(现在应答 fetch 为主线,XMLHttpRequest 作为历史对照)
  8. 说一下你所理解的同源政策。
  9. 你是如何解决跨域问题的?
  10. 你所理解的 JavaScript 事件循环机制是什么?
  11. 说一下对 Object.defineProperty() 的理解。
  12. 说一下图片的懒加载和预加载。
  13. 请求服务器数据,GET 和 POST 请求的区别是什么?
  14. Reflect 对象创建的目的是什么?
  15. require 模块引入的查找方式?
  16. 观察者模式和发布订阅模式有什么不同?
  17. 检查数据类型的方法有几种,分别是什么?
  18. 谈谈对 JSON 的了解。
  19. 进行哪些操作会造成内存泄漏?
  20. 谈谈你所理解的函数式编程。

# 15 道手写题

答案位置:全部见手写篇对应小节(节流防抖、深拷贝、call / apply / bind、柯里化、观察者、EventEmitter、JSONP、newObject.assign、URL 参数解析、数字格式化、instanceof、数组去重)。

  1. 实现 JS 的节流和防抖函数,两者的区别是什么?
  2. 实现 JS 中的深拷贝
  3. 手写 call 函数
  4. 手写 apply 函数
  5. 手写 bind 函数
  6. 实现柯里化函数
  7. 手写一个观察者模式
  8. 手动实现 EventEmitter(发布订阅模式)
  9. 手动实现 JSONP
  10. 手动实现 new 关键字
  11. 手动实现 Object.assign
  12. 实现解析 URL 参数为对象的函数
  13. JS 格式化数字(每三位加逗号)
  14. 手写 instanceof 关键字
  15. 手写数组去重的方法
webapp
公众号
开发者导航
切换夜间模式
点击侧边栏上一篇
点击侧边栏下一篇
折叠侧边栏
收起全部