面试题手册

梳理高频技术问题,帮助你按主题复习和查漏补缺。

前端阅读 245月27日 01:12

React 组件渲染过程是怎么样的?

React 的渲染分两个阶段:Render 阶段(协调 Reconciliation):状态变化 → 创建新的 Virtual DOM 树 → 和旧的 Virtual DOM 做 diff → 标记需要更新的节点。这个阶段是纯计算,没有副作用,React 18 可以中断和恢复(并发模式)。Commit 阶段:把 diff 结果应用到真实 DOM。这个阶段不可中断,React 保证 DOM 更新的原子性。commit 结束后触发 useLayoutEffect 同步执行,然后浏览器重绘,最后异步执行 useEffect。React 18 之前 render 不可中断。18 的并发渲染(Concurrent Features)可以在 render 阶段暂停低优先级更新,优先处理用户交互等高优先级任务。追问什么情况下 React 会跳过组件的渲染?shouldComponentUpdate 返回 false(class 组件)React.memo 包裹的组件 props 没变(浅比较)state 没变化时(setState 传入相同值,React 用 Object.is 判断)Context value 没变时(但 Provider 下的所有 Consumer 会在 Provider render 时重新渲染,和 value 是否变化无关——这是常见性能陷阱)useLayoutEffect 和 useEffect 执行的时机有什么不同?useLayoutEffect 在 DOM 变更后、浏览器绘制前同步执行(阻塞渲染)。useEffect 在浏览器绘制后异步执行。需要读取 DOM 布局、同步更新防止闪烁的场景用 useLayoutEffect。React 18 并发模式的 "可中断渲染" 是怎么实现的?基于时间切片(Time Slicing)——Render 阶段被切成 5ms 的小段,每段结束后检查是否有更高优先级任务。如果有就暂停当前渲染,先处理高优任务。实现依赖的是 MessageChannel(而非 requestIdleCallback,因为后者在后台标签页可能被暂停)。
前端阅读 125月27日 01:12

XML 和 JSON 的区别是什么?

JSON 现在是默认的数据交换格式。XML 在上一个时代扮演过同样角色。最大的区别:JSON 是数据格式,XML 是标记语言。JSON 直接表达对象、数组、字符串,XML 用标签包裹数据,更侧重文档结构。// JSON{ "name": "张三", "age": 30 }<!-- XML --><person> <name>张三</name> <age>30</age></person>JSON 的优势:更轻量、解析更快(JSON.parse vs DOM/SAX 解析)、天然映射 JS 对象、Schema 更简单。XML 仍有用的场景:需要属性+值+命名空间(SOAP 协议)、需要 DTD/Schema 验证、大量文档处理时 XPath/XSLT 更灵活。追问为什么 JSON 取代了 XML 做 Web API 的数据格式?两点:JS 生态的爆炸式增长(JSON 是 JS 原生支持的,XML 需要额外解析)和移动端的带宽敏感(JSON 更紧凑)。REST API + JSON 几乎成了标配。JSON 有什么缺点?不支持注释(JSONC 是变体)不支持日期类型(需转换成字符串或时间戳)浮点数精度问题(0.1 + 0.2 !== 0.3 在不同 JSON 解析器中处理不一致)没有二进制支持(Base64 编码后体积膨胀)XML 现在还用在哪?银行、政府系统(SOAP 协议)Office 文档格式(docx、xlsx 本质上是 XML 的 ZIP 包)SVG 图像Android 布局文件RSS/Atom 订阅
服务端阅读 985月27日 01:12

Node.js 如何开启多进程?进程之间如何通讯?

Node.js 用 child_process 模块创建子进程,用 cluster 模块做多核利用:child_process:spawn(command, args):启动一个新进程,返回流(适合长时间运行、大量输出的进程)exec(command, callback):启动 shell 执行命令,缓存输出后回调(适合短命令)fork(modulePath):特殊 spawn,创建 Node.js 子进程,自带 IPC 通道cluster:基于 fork 封装,能创建多个共享同一端口的 worker 进程(常见于 HTTP 服务利用多核)。进程通讯:fork 创建的父子进程间有 IPC 通道,用 process.send(msg) 和 process.on('message') 通信。底层实现:libuv 管道(pipe)。追问cluster 怎么实现多进程共享端口?主进程监听端口,将接收到的连接通过 Round-Robin 分发给 worker 进程。worker 不直接监听端口,而是接收主进程分配的连接句柄。Linux 上也可用 SO_REUSEPORT 内核级别的分发。fork 和 spawn 的区别?fork 是 spawn 的特殊版——专门 fork Node.js 进程,自动建立 IPC 通道。spawn 启动任何命令,流式处理输出,适合与外部程序交互。PM2 的 cluster 模式和 fork 模式有什么区别?cluster:PM2 用 Node.js cluster 模块,多实例共享端口,自动负载均衡fork:PM2 只是用 child_process.fork 启动多个实例,需要不同端口或用 Nginx 做反向代理
前端阅读 685月27日 01:12

TCP 建立连接需要经过哪几步?

TCP 三次握手建立连接:客户端 → SYN:客户端发 SYN=1,seq=x(随机初始序列号)。客户端进入 SYN-SENT 状态服务端 → SYN+ACK:服务端回 SYN=1,ACK=1,seq=y,ack=x+1。服务端进入 SYN-RCVD 状态客户端 → ACK:客户端发 ACK=1,seq=x+1,ack=y+1。双方进入 ESTABLISHED 状态为什么是三次不是两次?因为要防止已失效的连接请求到达服务端。如果只有两次,客户端发了一个 SYN 因为网络延迟没到,客户端超时重发了一个新的 SYN 建立了连接。之后旧的 SYN 到达服务端,服务端以为这是新连接,回 SYN+ACK 就建立了连接——但客户端根本不知道这个连接的存在。追问为什么不是四次握手?理论上四次(SYN → SYN+ACK → ACK → 服务端收到 ACK 确认)更稳妥。但第三步的 ACK 可以和服务端收到 ACK 合并——服务端只需要知道客户端收到了自己的 SYN+ACK 就够。额外的第四次是冗余的。SYN 泛洪攻击是什么?攻击者发送大量 SYN 但不回 ACK,导致服务端大量连接处于 SYN-RCVD 半连接状态,耗尽服务端资源。防御:SYN Cookie(服务端不分配资源,用 Cookie 验证客户端是真的)、减少 SYN-RCVD 超时时间。TCP 四次挥手为什么多一次?因为 TCP 是全双工的——每个方向都要独立关闭。客户端 FIN 表示"我说完了",服务端 ACK 表示"知道了",但如果服务端还有数据要发,发完后再 FIN。所以是 FIN → ACK → FIN → ACK 四步。
计算机基础阅读 925月27日 01:11

GET 和 POST 的区别是什么?何时使用 POST?

从 HTTP 协议本身看,GET 和 POST 只有两个本质区别:语义不同:GET 是"获取"(安全、幂等),POST 是"提交数据以处理"(不幂等)POST 有 body,GET 没有(GET 也可以有 body,但 RFC 不推荐,很多实现不支持)其他所谓的区别——"GET 参数在 URL 里,POST 在 body 里"、"GET 参数长度有限制"、"GET 被浏览器缓存"——要么是实现细节,要么是浏览器的行为,不是协议本身的约束。何时用 POST:创建/修改资源、提交表单、需要传大量数据、需要隐藏敏感参数(虽然 body 也不安全,HTTPS 才是真正保护)。追问GET 请求真的不能有 body 吗?RFC 7231 没有禁止,但建议不要给 GET 加 body。实际上 fetch 和 XMLHttpRequest 都支持带 body 的 GET,但浏览器 <form> 和 <a> 不支持,很多中间件/代理也不处理 GET body。PUT 和 POST 有什么区别?都是提交数据,但语义不同:PUT 是幂等的(多次调用结果相同——替换指定位置的资源),POST 不是(多次调用可能创建多个资源)。PUT 的 URL 通常确定具体资源(/users/1),POST 是集合 URL(/users)。POST 比 GET 更安全吗?不安全。POST body 在 HTTP 下仍然是明文传输,只是 URL 里看不到而已。HTTPS 下二者都加密后才发送,POST 的"安全性"优势在 HTTPS 下不存在。真正的区别是 POST 数据不会出现在日志/浏览器历史/server log 的 URL 中。
前端阅读 245月27日 01:10

webpack 的热更新原理是什么?详细聊聊热更新的流程

HMR(Hot Module Replacement)的核心流程:webpack-dev-server 启动 WebSocket 服务,和浏览器建立长连接文件变化 → webpack 重新编译 → 生成两个文件:[hash].hot-update.json(变更模块清单)和 [hash].hot-update.js(变更模块代码)通过 WebSocket 推送 hash 事件给浏览器浏览器用 AJAX 拉 hot-update.json,用 JSONP 拉 hot-update.jsHMR runtime 找到变更的模块,执行 module.hot.accept 注册的回调如果模块没有注册 accept,HMR runtime 向上冒泡,直到找到 accept 或刷新整个页面Vue-loader、style-loader 等 loader 内部自动调用了 module.hot.accept,所以改 .vue 文件能无刷新更新。追问为什么需要两步拉取(json + js)?hot-update.json 先确认哪些模块变了,如果当前页面没有引用变更模块,就不需要拉 hot-update.js。另外 json 由 webpack-dev-server 直接提供(内存文件系统),js 则走 JSONP 来避免跨域问题。React Fast Refresh 和普通 HMR 有什么区别?React Fast Refresh 在 HMR 基础上做了 React 组件的"签名"匹配——换掉的组件如果有相同的 hooks 调用和组件的导出签名,就保留下面的组件状态(state 不丢失)。普通 HMR 只是替换模块代码,状态会重置。HMR 失效了怎么排查?module.hot.accept 是否注册(检查对应 loader 是否配置正确)文件路径大小写不一致(macOS 不敏感但 webpack 敏感)配置文件中 hot: true 和 HotModuleReplacementPlugin 是否启用
计算机基础阅读 1145月27日 01:10

HTTP 有哪些常用的状态码?

按分类记:2xx 成功:200 OK:请求成功201 Created:创建资源成功(POST 返回)204 No Content:成功但无响应体(DELETE 后常见)3xx 重定向:301 Moved Permanently:永久重定向(浏览器会缓存,下次直接跳)302 Found:临时重定向304 Not Modified:资源未修改,用缓存(配合 If-Modified-Since/ETag)307/308:和 301/302 类似,但 POST 转 GET 行为不同4xx 客户端错误:400 Bad Request:请求格式错误401 Unauthorized:未认证403 Forbidden:已认证但无权限404 Not Found:资源不存在405 Method Not Allowed:方法不对(比如用 GET 调了 POST 接口)429 Too Many Requests:被限流5xx 服务端错误:500 Internal Server Error:服务端内部错误502 Bad Gateway:网关/代理收到无效上游响应503 Service Unavailable:服务暂不可用(维护/过载)504 Gateway Timeout:网关超时追问301 和 302 的区别?301 是永久的——浏览器会缓存重定向目标,之后相同 URL 直接跳转,不用再请求原地址。SEO 权重转移。302 是临时的——每次都会请求原地址再跳转。语义不同,对 SEO 和缓存影响很大。401 和 403 怎么区分?401 是"你是谁?"——没登录或 token 过期,需要你去认证。403 是"我知道你是谁,但不让你看"——认证通过了但权限不够。502 和 504 的区别?502 是网关从上游收到了无效/不完整的响应(服务崩溃、配置错误)。504 是网关在规定时间内没等到上游响应(超时)。排查方向:502 看服务有没有挂,504 看服务是不是太慢。
前端阅读 345月27日 01:10

Chrome 打开一个页面需要启动多少进程?分别有哪些进程?

Chrome 是多进程架构,主要进程:Browser 进程(1 个):主进程,管 UI(地址栏、书签)、网络请求、文件访问。协调其他进程。Renderer 进程(每个标签页一个):渲染页面内容(HTML、CSS、JS)。沙箱隔离,一个页面崩不影响其他页面。GPU 进程(1 个):处理 GPU 任务(CSS 3D 变换、WebGL、视频解码)。Plugin 进程(按需):隔离运行的插件(Flash 等,现已很少)。Network 进程(1 个,较新版本):独立的网络进程。Utility 进程(按需):音频、扩展等。同一站点(same-site)的标签页可能共享 Renderer 进程以节省内存。具体数量取决于你开了多少标签页、多少扩展。追问为什么 Chrome 用多进程而不是多线程?稳定性和安全性。如果一个标签页崩溃或卡死,只影响那个 Renderer 进程,不会拖垮整个浏览器。沙箱机制也只限制单进程的权限。缺点是内存占用高,所以 Chrome 引入了进程共享(同一站点共享 Renderer 进程)。Renderer 进程里是什么?Renderer 进程包含:主线程(JS 执行、样式计算、布局)、合成线程(处理滚动、动画)、Raster 线程(将绘制命令转成位图)、Worker 线程等。主线程阻塞是页面卡顿的主要原因。内存不够时 Chrome 会怎么做?Chrome 会动态管理:冻结后台标签页的进程(节省内存)、优先杀掉非活动标签页的 Renderer 进程、同一站点合用一个 Renderer 进程。开大量标签页时内存压力还是很大。
计算机基础阅读 435月27日 01:10

什么是对称加密和非对称加密?

对称加密:加密和解密用同一把密钥。快,适合加密大量数据。问题是怎么安全地把密钥传给对方——密钥传输过程中可能被截获。代表:AES、DES、ChaCha20。非对称加密:一对密钥——公钥加密、私钥解密。公钥可以公开,任何人用公钥加密,只有持有私钥的人能解密。解决了对称加密的密钥分发问题,但计算慢,不适合大数据。代表:RSA、ECC。实际应用中二者组合:用非对称加密传递对称密钥,之后的通信全部用对称加密。HTTPS 的 TLS 握手就是这样干的——RSA/ECDHE 交换密钥 → AES 加密通信内容。追问HTTPS 用的是对称还是非对称?都用。TLS 握手阶段用非对称(RSA/ECDHE)协商出一个对称密钥(Session Key),之后的数据传输用这个对称密钥做 AES 加密。取长补短。为什么非对称加密更安全但更慢?非对称加密的数学基础是大数分解(RSA)或椭圆曲线(ECC),运算量远大于 AES 的位运算。RSA 2048 位密钥加密几百字节就要几十毫秒,AES 加密几 MB 数据只要微秒级。前端的 crypto.subtle 能做非对称加密吗?能。crypto.subtle.generateKey 支持 RSA-OAEP 和 ECDH。但大部分场景 JD 不需要在前端做非对称加密——前端代码公开,私钥无处存放。通常前端只是用 HTTPS 加密传输,非对称部分在 TLS 层自动完成。
前端阅读 275月27日 01:09

浏览器为什么要有同源限制?

同源策略是浏览器最核心的安全机制——限制一个源(协议+域名+端口都相同)的脚本去访问另一个源的资源。没有同源限制会怎样?你打开了 bank.com 登录了,另一个标签页打开了 evil.com。evil.com 的 JS 可以直接用 fetch 发请求到 bank.com/api/transfer——浏览器会自动带上你的登录 cookie,钱就转走了。同源策略阻止了这个。同源限制主要限制:1) AJAX 跨域请求;2) 跨 iframe/窗口的 DOM 操作;3) localStorage/Cookie 的跨域访问。跨域解决方案:CORS(服务端设 Access-Control-Allow-Origin)、JSONP(老方法,利用 script 标签不受同源限制)、代理(同源服务端转发)。追问为什么 script/img 标签不受同源限制?这是历史原因和功能需求——网页需要加载 CDN 上的脚本和图片。但 <script> 加载完会以当前域执行(所以有 XSS 风险),<img> 只能渲染不能读取像素数据(防止窃取)。资源加载的宽松和 API 访问的严格是两个层面的事。同源策略能防止 CSRF 吗?不完全能。CSRF 的请求能发出去(form 提交、img 加载都可以跨域),同源策略只阻止 JS 读响应。防止 CSRF 得靠 CSRF Token 或 SameSite Cookie。跨域请求发出去但响应被拦截,服务端收到请求了吗?收到了。浏览器是收到响应后发现没有 CORS 头才拦截的。所以服务端需要用 CORS 头来控制,不能用"浏览器会拦截"来保护服务端。