文章目录

牛客面经整理:小红书前端一面(含 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-MatchLast-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.invokeipcMain.handle(请求-响应,Promise,推荐)。
    • ipcRenderer.sendipcMain.on(单向事件,需自己做 ack/超时)。
  • “不可靠传输”常见风险:渲染进程崩溃/刷新导致消息丢失、顺序不一致、重复发送;需要幂等、序列号、ack、重试与超时。
  • 白名单机制(安全要点):
    • preload 通过 contextBridge 只暴露允许的 API。
    • 主进程只响应白名单 channel/方法,校验参数 schema,拒绝任意执行(避免 RCE)。

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)