牛客面经整理:小红书前端一面(含 Electron)(十八)
收录日期:2026-04-23
关键词:前端、浏览器、网络、WebSocket、Electron、TypeScript
1. React:useState 声明的 state 没“初始化”就取用,会不会阻塞渲染?
参考答案
useState(initialState)的初始值会在首次渲染时确定,不存在“没初始化就读取”的情况。- 阻塞的根因通常是:渲染阶段做了重计算/同步 IO/大量 DOM(或递归),而不是 state 本身。
- 优化思路:
- 初始值昂贵时用惰性初始化:
useState(() => heavyInit())。 - 把重计算移到 memo 或 web worker(适用时)。
- 初始值昂贵时用惰性初始化:
2. 浏览器加载全过程:DOM 解析、JS 资源加载两种方式
参考答案
- 主流程:HTML → DOM;CSS → CSSOM;合成渲染树 → layout → paint → composite。
- JS 加载方式与阻塞:
- 普通
<script>:会阻塞 HTML 解析(下载可能并行,但执行会阻塞)。 defer:并行下载,等 DOM 解析完按顺序执行。async:并行下载,下载完立刻执行(顺序不保证)。type="module":默认 defer 语义,支持 ESM。
- 普通
3. HTTP 和 HTTPS 的区别?加密是怎么加的?
参考答案
- HTTPS 通过 TLS 提供加密、完整性、身份认证。
- 机制(简化):
- 证书校验服务器身份;
- 协商并生成对称密钥;
- 后续用对称加密传输(快),关键交换用非对称(安全)。
4. 浏览器缓存有哪些?怎么用?
参考答案
- 强缓存:
Cache-Control: max-age(不发请求直接用缓存)。 - 协商缓存:
ETag/If-None-Match、Last-Modified/If-Modified-Since(发请求,未变更返回 304)。 - 前端实践:
- 静态资源用内容 hash(长缓存)。
- HTML 入口短缓存或不缓存,保证版本可控。
5. 常见 HTTP 状态码及含义
参考答案
- 2xx:成功(200/204)。
- 3xx:重定向/缓存(301/302/304)。
- 4xx:客户端问题(400/401/403/404/429)。
- 5xx:服务端问题(500/502/503/504)。
6. WebSocket 错误监控与断联重连怎么做?
参考答案
- 监控:
- 连接事件:open/close/error;
- 心跳:ping/pong 或应用层心跳消息,监测 RTT 与丢包;
- 业务指标:消息延迟、重连次数、失败率。
- 重连策略:
- 指数退避 + 抖动(jitter),避免所有客户端同时重连。
- 区分“主动关闭/网络断开/服务端踢下线”,给出不同提示与策略。
- 登录态变更时要重建连接并重新订阅频道。
7. Electron:进程间通信(IPC)怎么做?ipcMain 不可靠传输与白名单机制是什么?
参考答案
- 进程模型:主进程(Main)管理窗口与系统资源;渲染进程(Renderer)跑网页与 UI;可有 preload(隔离桥)。
- IPC 常见方式:
ipcRenderer.invoke↔ipcMain.handle(请求-响应,Promise,推荐)。ipcRenderer.send↔ipcMain.on(单向事件,需自己做 ack/超时)。
- “不可靠传输”常见风险:渲染进程崩溃/刷新导致消息丢失、顺序不一致、重复发送;需要幂等、序列号、ack、重试与超时。
- 白名单机制(安全要点):
- preload 通过
contextBridge只暴露允许的 API。 - 主进程只响应白名单 channel/方法,校验参数 schema,拒绝任意执行(避免 RCE)。
- preload 通过
8. TypeScript:联合类型是什么?怎么做类型收窄?
参考答案
- 联合类型:
A | B,表示值可能是多种类型之一。 - 收窄方式:
typeof/instanceof。in操作符判断属性存在。- 判别联合(discriminated union):用
type: 'a' | 'b'字段做分支。 - 自定义类型守卫:
function isFoo(x: any): x is Foo { ... }。
9. 手撕:行列升序矩阵中查找一个数字(思路)
参考答案
- 经典解法:从右上角(或左下角)开始。
- 若当前值大于 target:左移(排除一列)。
- 若当前值小于 target:下移(排除一行)。
- 复杂度:时间
O(m+n),空间O(1)。