字节暑期前端一面整理笔记(三十七)
1. Sdk 干什么,你为什么会在公司接触这个业务
答案
SDK 本质上是对某类能力的封装,目的是让业务侧更低成本地接入统一能力。
- 常见场景有埋点、登录、支付、上传、AI 能力接入、编辑器能力接入。
- 公司里会接触 SDK,通常是因为很多业务线都要复用同一套能力,不能每个项目都从零写一遍。
- 一个好的 SDK 要解决接入简单、版本兼容、错误兜底和可扩展的问题。
2. 插件是什么个逻辑
答案
插件机制的核心是“在不改核心代码的前提下扩展能力”。
- 一般会预留生命周期或 Hook。
- 插件通过注册这些 Hook,把自己的逻辑插进去。
- 好处是核心系统保持稳定,扩展能力交给外部实现。
- 常见于构建工具、编辑器、CLI、业务平台。
3. sdk 的 treeshaking 前后的大小有没有对比过
答案
SDK 本质上是对某类能力的封装,目的是让业务侧更低成本地接入统一能力。
- 常见场景有埋点、登录、支付、上传、AI 能力接入、编辑器能力接入。
- 公司里会接触 SDK,通常是因为很多业务线都要复用同一套能力,不能每个项目都从零写一遍。
- 一个好的 SDK 要解决接入简单、版本兼容、错误兜底和可扩展的问题。
4. treeshaking 的逻辑
答案
Tree Shaking 的本质是删除“没有被用到的导出代码”。
- 它依赖静态分析,所以最适合 ESM。
- 常见发生在打包阶段,构建工具会分析依赖图和导出引用关系,把未使用代码标记为可删除。
- CommonJS 因为
require是运行时执行、可动态分支,静态分析能力弱,所以 Tree Shaking 效果受限。 - 如果问体积对比,应该回答:会对比打包前后的 bundle 体积、gzip/br 体积和实际加载资源变化。
5. treeshaking 是在哪个阶段进行
答案
Tree Shaking 的本质是删除“没有被用到的导出代码”。
- 它依赖静态分析,所以最适合 ESM。
- 常见发生在打包阶段,构建工具会分析依赖图和导出引用关系,把未使用代码标记为可删除。
- CommonJS 因为
require是运行时执行、可动态分支,静态分析能力弱,所以 Tree Shaking 效果受限。 - 如果问体积对比,应该回答:会对比打包前后的 bundle 体积、gzip/br 体积和实际加载资源变化。
6. treeshaking 在 CommonJS 有什么限制
答案
Tree Shaking 的本质是删除“没有被用到的导出代码”。
- 它依赖静态分析,所以最适合 ESM。
- 常见发生在打包阶段,构建工具会分析依赖图和导出引用关系,把未使用代码标记为可删除。
- CommonJS 因为
require是运行时执行、可动态分支,静态分析能力弱,所以 Tree Shaking 效果受限。 - 如果问体积对比,应该回答:会对比打包前后的 bundle 体积、gzip/br 体积和实际加载资源变化。
7. monorepo 底层逻辑架构是什么样
答案
Monorepo 是把多个相关包放在同一个仓库管理。
- 优点是依赖统一、代码共享方便、原子提交和统一 CI 更容易。
- 缺点是仓库治理复杂、构建和权限边界需要额外设计。
- 它和微前端不是一回事:Monorepo 解决的是代码仓库组织问题,微前端解决的是前端运行时拆分和独立部署问题。
8. md 里面的 ai 相关是什么逻辑
答案
这类题核心是把你的 AI 产品链路说清楚。
- 如果当前只支持文字,就直接说明当前能力边界,不要虚构支持图片。
- 再补充未来如果扩展图片、文件、多模态,需要新增的协议字段、渲染组件和状态管理。
- 项目里 AI 的主链路通常是:用户输入 -> 上下文组装 -> 模型请求 -> 流式返回 -> 前端增量渲染 -> 会话持久化。
9. md 的性能优化逻辑
答案
如果这里指 Markdown 编辑或渲染性能,核心是避免每次小变动都整段重算。
- 解析和渲染尽量做增量处理。
- 高频输入时做节流、分帧或 Worker 处理。
- 大文档场景要控制 DOM 数量和渲染粒度。
10. 有没有其他的性能优化
答案
可以从资源、渲染、交互和缓存几个维度补充。
- 资源层:拆包、压缩、懒加载。
- 渲染层:虚拟列表、减少重排重绘。
- 交互层:防抖节流、长任务拆分。
- 缓存层:接口缓存、静态资源缓存。
11. react 周期
答案
如果说的是类组件生命周期,主线是:
- 挂载:
constructor->render->componentDidMount - 更新:
shouldComponentUpdate->render->componentDidUpdate - 卸载:
componentWillUnmount
如果说的是函数组件,可以补充:函数组件没有传统生命周期方法,更多通过 useEffect / useLayoutEffect 描述挂载、更新和卸载阶段的副作用。
12. 虚拟 diff 对比
答案
虚拟 DOM Diff 不是做最优树编辑距离,而是做工程上的高效折中。
- 先把旧树和新树做同层比较。
- 默认认为不同层级的节点不会跨层复用。
- 列表场景通过
key标识稳定节点,减少错误复用和无效移动。 - 这样可以把复杂度控制在可接受范围内。
13. 为什么 hooks 不能写在条件里面,如果一定要写怎么办
答案
Hooks 不能写在条件分支里,是因为 React 依赖固定的 Hook 调用顺序来关联状态。
- 某次渲染进了条件、某次没进,Hook 顺序就会错位。
- 一旦错位,后面的状态和副作用都会对应错。
- 如果一定要做条件逻辑,应该把条件放进 Hook 内部,或者拆成子组件。
14. git 多个 commit 怎么合并一个
答案
本地多个 commit 合并成一个,最常见做法是 git rebase -i。
- 选择要整理的提交范围。
- 把后续提交改成
squash或fixup。 - 最后合成一个新的提交记录。
如果已经推送到公共分支,要谨慎改历史,避免影响别人。
15. sass、less、tailwind css 区别
答案
Sass 和 Less 都是 CSS 预处理器,提供变量、嵌套、函数、混入等能力;Tailwind 则是原子化 CSS 工具类体系。
- Sass / Less 更偏“写更强的 CSS”。
- Tailwind 更偏“用约束好的类名快速组合界面”。
- 预处理器适合已有样式体系的增强,Tailwind 更适合规范统一、组件化程度高的项目。
16. 手撕 bind
答案
手写 bind 要处理两个核心点:绑定 this,以及支持 new 调用。
- 返回一个新函数。
- 新函数执行时把预置参数和调用参数拼起来,再用
apply调原函数。 - 如果新函数被
new调用,this应该指向新实例,而不是原先绑定对象。 - 如果要完整实现,还要处理原型链继承。
17. 数字转汉字整数
答案
这题一般按“分段处理”来做。
- 先把数字按个、十、百、千、万、亿这些单位拆开。
- 每四位作为一个分段处理,再拼接“万、亿”等大单位。
- 重点难点是连续零只读一个零,以及十几开头时通常省略“一”。