文章目录

字节抖音前端暑期二面整理笔记(三十五)

1. 你说的打包技术指的是 Webpack 还是 Vite

答案

如果项目里既提过 Webpack 又提过 Vite,建议先说明主用哪一个,再对比原因。

  1. Webpack 生态更老更全,适合历史项目和高度定制场景。
  2. Vite 开发态基于原生 ESM,冷启动和热更新通常更快,适合现代前端项目。
  3. 如果面试官追问,一定补上:开发态和生产构建的策略不一样,不能只说“Vite 更快”。

2. 你是前后端都开发吗,包括 Node.js 吗

答案

可以回答成“我有前后端协作能力,Node.js 主要用于中间层和工程化场景”。

  1. Node.js 适合做 BFF、网关、SSR、脚手架和 I/O 密集型服务。
  2. 如果自己项目里做过接口转发、上传服务、流式返回,就可以直接举例。
  3. 面试里不要把 Node.js 说成“万能后端”,要强调它更擅长的场景。

3. 讲一下浏览器里的宏任务和微任务

答案

事件循环的主线是:执行一轮宏任务,然后清空微任务队列,必要时进行渲染,再进入下一轮。

  1. 常见宏任务:setTimeoutsetInterval、I/O、UI 事件。
  2. 常见微任务:Promise.thenqueueMicrotaskMutationObserver
  3. 所以输出顺序题一般先看同步代码,再看微任务,最后看下一轮宏任务。

4. 浏览器事件循环和 Node.js 事件循环有什么区别

答案

事件循环的主线是:执行一轮宏任务,然后清空微任务队列,必要时进行渲染,再进入下一轮。

  1. 常见宏任务:setTimeoutsetInterval、I/O、UI 事件。
  2. 常见微任务:Promise.thenqueueMicrotaskMutationObserver
  3. 所以输出顺序题一般先看同步代码,再看微任务,最后看下一轮宏任务。

5. 看代码说答案:事件循环相关

答案

事件循环的主线是:执行一轮宏任务,然后清空微任务队列,必要时进行渲染,再进入下一轮。

  1. 常见宏任务:setTimeoutsetInterval、I/O、UI 事件。
  2. 常见微任务:Promise.thenqueueMicrotaskMutationObserver
  3. 所以输出顺序题一般先看同步代码,再看微任务,最后看下一轮宏任务。

6. 强缓存和协商缓存有什么区别

答案

强缓存和协商缓存的区别在于:是否需要再向服务器确认。

  1. 强缓存靠 Cache-ControlExpires,命中时浏览器直接用本地缓存,不发请求。
  2. 协商缓存会发请求,由服务端根据 ETag / Last-Modified 判断是否返回 304
  3. 实战里常见做法是静态资源走强缓存 + 文件指纹,HTML 走协商缓存。

7. TypeScript 里 type 和 interface 有什么区别

答案

使用 TypeScript 的核心价值是提升可维护性和协作效率。

  1. 它能在开发阶段提前发现类型错误。
  2. 对接口模型、复杂表单、组件库和状态管理非常有帮助。
  3. 重构时更安全,IDE 提示也更完整。
  4. 团队项目里,类型本身也是一种文档。

8. 项目中 type 和 interface 怎么选择

答案

interface 更适合描述对象结构,支持声明合并;type 更灵活,适合联合类型、交叉类型和别名。

  1. 描述接口对象、组件 props、返回值模型时,很多团队更偏向用 interface
  2. 做复杂类型运算、联合字面量、映射类型时,更适合用 type
  3. 本质不是谁绝对更好,而是看团队规范和场景。

9. 介绍一下 SSE 的实现

答案

SSE 的实现核心是服务端持续推送事件流,客户端持续监听。

  1. 服务端返回 text/event-stream
  2. 客户端通过 EventSource 或流式读取持续接收数据。
  3. 每条消息按事件格式解析,再更新页面状态。

10. SSE 和 WebSocket 有什么区别

答案

SSE 和 WebSocket 的核心区别是通信方向和适用场景。

  1. SSE 是服务端单向推送,基于 HTTP,天然适合大模型文本流、通知流、日志流。
  2. WebSocket 是全双工通信,更适合聊天、协同编辑、实时互动。
  3. AI 对话里如果主要是服务端不断吐内容,SSE 往往更简单、更稳定,也更容易复用现有 HTTP 鉴权和网关体系。
  4. 如果需要客户端高频主动发消息、双向实时同步,WebSocket 更合适。

11. 为什么你的 AI 对话项目选择 SSE 而不是 WebSocket

答案

SSE 和 WebSocket 的核心区别是通信方向和适用场景。

  1. SSE 是服务端单向推送,基于 HTTP,天然适合大模型文本流、通知流、日志流。
  2. WebSocket 是全双工通信,更适合聊天、协同编辑、实时互动。
  3. AI 对话里如果主要是服务端不断吐内容,SSE 往往更简单、更稳定,也更容易复用现有 HTTP 鉴权和网关体系。
  4. 如果需要客户端高频主动发消息、双向实时同步,WebSocket 更合适。

12. 你的多轮对话项目只支持文字,还是也支持图片修改

答案

这类题核心是把你的 AI 产品链路说清楚。

  1. 如果当前只支持文字,就直接说明当前能力边界,不要虚构支持图片。
  2. 再补充未来如果扩展图片、文件、多模态,需要新增的协议字段、渲染组件和状态管理。
  3. 项目里 AI 的主链路通常是:用户输入 -> 上下文组装 -> 模型请求 -> 流式返回 -> 前端增量渲染 -> 会话持久化。

13. 如果要支持图片加工创作,和纯文字对话设计上有什么不同

答案

多模态流式内容一般不能只当纯字符串处理,推荐把服务端返回统一抽象成消息片段流。

  1. 每个片段带上 type,例如 textimagepdfmarkdowncomponent
  2. 前端先按协议解析,再分发给不同渲染器组件。
  3. 文本流可以增量更新;图片、文件类内容更适合先展示占位状态,拿到完整地址后再渲染。
  4. 多轮图片编辑相比纯文字对话,额外要管理素材引用、版本关系、操作指令和结果回显。

14. 多轮图片编辑或多轮文字对话出现意图偏移,怎么优化

答案

多模态流式内容一般不能只当纯字符串处理,推荐把服务端返回统一抽象成消息片段流。

  1. 每个片段带上 type,例如 textimagepdfmarkdowncomponent
  2. 前端先按协议解析,再分发给不同渲染器组件。
  3. 文本流可以增量更新;图片、文件类内容更适合先展示占位状态,拿到完整地址后再渲染。
  4. 多轮图片编辑相比纯文字对话,额外要管理素材引用、版本关系、操作指令和结果回显。

15. 上下文过长导致语义偏移,工程上怎么优化

答案

上下文过长时,不能把所有历史消息无脑拼给模型,通常要做分层管理。

  1. 近期强相关消息保留原文。
  2. 远期历史做摘要压缩,只保留结论、约束和关键事实。
  3. 对知识性内容走 RAG 检索,不直接全量塞进上下文。
  4. 如果出现意图偏移,可以把系统约束、用户目标和关键上下文单独固定在高优先级区域。

16. 你的上下文摘要压缩策略是怎么做的

答案

上下文过长时,不能把所有历史消息无脑拼给模型,通常要做分层管理。

  1. 近期强相关消息保留原文。
  2. 远期历史做摘要压缩,只保留结论、约束和关键事实。
  3. 对知识性内容走 RAG 检索,不直接全量塞进上下文。
  4. 如果出现意图偏移,可以把系统约束、用户目标和关键上下文单独固定在高优先级区域。

17. 讲一下你虚拟列表的整体实现思路

答案

虚拟列表实现思路一般是:

  1. 根据滚动位置计算当前可视区范围。
  2. 只渲染这一小段数据。
  3. 通过占位容器撑开整体滚动高度。
  4. 滚动时动态更新起止索引。

18. Markdown 安全渲染里怎么防止 XSS

答案

Markdown 安全渲染的核心是“不要把不可信内容直接当 HTML 执行”。

  1. 先把 Markdown 解析成结构化 AST。
  2. 对 HTML 标签、属性做白名单过滤,危险协议如 javascript: 必须拦截。
  3. 对富文本渲染通常会配合 DOMPurify 一类库做二次清洗。
  4. 如果支持代码块、链接、图片,也要分别校验 URL、事件属性和内联脚本。

19. 为什么选择做后台管理系统这个项目

答案

项目题建议按“背景、目标、职责、难点、结果”来回答。

  1. 先说项目是做什么的,面向谁,解决什么问题。
  2. 再说页面结构和核心模块,比如会话区、输入区、历史记录、设置区、文件区等。
  3. 说明自己负责的部分,不要泛泛说“都做了”。
  4. 最后讲 1 到 2 个真正的难点,比如流式渲染、状态管理、性能优化、上传链路、权限模型,并补充最终效果。

20. 大文件分片上传是怎么实现的

答案

文件上传这类题建议按完整链路回答:

  1. 前端先按大小阈值切片,通常 2MB 到 10MB 比较常见。
  2. 上传前计算文件 hash,服务端据此判断是否已存在完整文件或部分分片。
  3. 断点续传时,前端先查询已上传分片列表,只补传缺失分片。
  4. 全部分片上传完成后,通知服务端按顺序合并。
  5. 秒传一般基于完整文件 hash;分片 hash 更多用于断点续传和重复分片复用。
  6. 分片不是越多越好:分太小请求数会暴涨,分太大失败重传成本高,所以要结合网络、文件大小和后端承载能力权衡。

21. JWT 双 Token 登录机制是怎么设计的

答案

双 Token 方案一般是 access token + refresh token

  1. access token 生命周期短,用于日常接口访问。
  2. refresh token 生命周期长,用于换取新的 access token
  3. 单点登录通常依赖统一身份中心,多个系统共享登录态,前端只是消费统一登录结果。
  4. 生产里要考虑并发刷新、失效重登和登出联动。

22. 怎么基于双 Token 实现单点登录

答案

双 Token 方案一般是 access token + refresh token

  1. access token 生命周期短,用于日常接口访问。
  2. refresh token 生命周期长,用于换取新的 access token
  3. 单点登录通常依赖统一身份中心,多个系统共享登录态,前端只是消费统一登录结果。
  4. 生产里要考虑并发刷新、失效重登和登出联动。

23. 权限管理是怎么设计的

答案

权限管理一般分四层:

  1. 路由级:控制页面能不能进。
  2. 菜单级:控制导航是否可见。
  3. 按钮级:控制具体操作是否可点。
  4. 数据级:控制能看到哪些数据。

前端主要负责展示和交互限制,真正的权限校验一定要以后端为准。


24. AI 生成代码和你手写代码的比例大概是多少

答案

这题不建议报一个夸张比例,重点是说明边界。

  1. 重复性、样板化代码会更多借助 AI。
  2. 核心业务逻辑、架构设计和线上修复仍然以自己主导为主。
  3. 更好的表达是:AI 提升了效率,但最终质量和正确性仍由我负责。

25. 看代码说答案:this 指向相关

答案

判断 this 指向时,按优先级看:

  1. new 绑定。
  2. call/apply/bind 显式绑定。
  3. 隐式绑定,也就是谁调用函数,this 指向谁。
  4. 默认绑定,浏览器非严格模式下一般是 window,严格模式下是 undefined
  5. 箭头函数不适用这套规则,它只看定义时的外层作用域。

26. 严格模式下 this 的输出有什么变化

答案

严格模式下,this 的默认绑定会更严格。

  1. 普通函数直接调用时,非严格模式下 this 通常指向 window;严格模式下是 undefined
  2. 作为对象方法调用时,this 仍然指向调用它的对象。
  3. 箭头函数没有自己的 this,始终继承外层词法作用域。

27. 实现带最大并发数限制的 Promise.all

答案

带并发限制的 Promise.all 核心是维护一个“运行中任务池”。

  1. 同时只启动 k 个任务。
  2. 任意一个任务完成后,再从等待队列里补一个新的进去。
  3. 结果数组要按输入顺序回填,而不是按完成顺序 push。
  4. 全部任务结束后再统一 resolve;如果设计成首错即停,要在出错时及时 reject。

28. LC101 对称二叉树

答案

这题本质是判断左右子树是否互为镜像。

  1. 递归比较左子树的左节点和右子树的右节点。
  2. 再比较左子树的右节点和右子树的左节点。
  3. 如果两个节点都为空,返回 true;一个空一个不空或值不同,返回 false。