【推荐】城市灾害应急管理系统【面试模拟题目——字节跳动面试原题】
字节面试题目
下面是对您提供的前端面试题的逐题详细回答。我会按照面试官的视角构造完整的回答,语言尽量专业清晰,便于他们理解你的思考方式和实际经验。
✅ 一、项目经验与3D相关
1. 第一个项目人数,如何分工,主要负责的功能
我们团队一共5人,分为前端3人,后端2人。
我主要负责的模块包括:
- 3D地图视图模块开发
- 数据可视化(热力图、柱状图、轨迹线)
- 与后端联调接口,数据动态加载渲染
- 前端组件封装与性能优化
团队其他成员分别负责界面设计实现、权限管理模块和测试部署。
2. 使用到的三维地图库的底层实现原理(汗流浃背)
我们使用的是 Cesium.js。底层主要通过 WebGL 实现三维渲染,其实现核心有:
- 加载瓦片数据(3D Tiles、Terrain、Imagery)
- 使用 地理坐标转为笛卡尔坐标系 进行三维计算
- GPU加速渲染地形、建筑、模型等
- 利用帧循环(render loop)实时更新场景
Cesium本质上是对WebGL封装并做了空间几何/图层的数据管理,用户操作(缩放、旋转)通过摄像机(Camera)系统来处理。
3. 使用了什么Web技术实现3D效果
我们主要使用以下技术实现3D效果:
- WebGL:低层图形接口(通过Cesium封装)
- Canvas:用于某些2D覆盖图层绘制
- Three.js(试用):补充展示某些轻量模型(如glTF)
- requestAnimationFrame:实现动画帧控制
- 着色器语言GLSL:通过Cesium Shader语法控制光照/材质等
4. Canvas 和 WebGL 有没有了解(裂)
有一定了解:
- Canvas 是2D绘图上下文,适用于图表、图形等
- WebGL 是基于OpenGL ES的JavaScript API,可操作GPU绘制3D图形
- Canvas绘制是像素级,CPU计算多、性能差
- WebGL可以实现3D、粒子系统,通过GPU加速,效率高
5. 参与这个项目之后技术上的成长有哪些
技术成长包括:
- 掌握了 WebGL 渲染机制 和地图相关三维坐标系变换
- 理解了异步数据渲染和 大规模模型加载优化
- 提升了组件复用能力,抽象了若干通用组件(图层控制、图例、模型动画控制)
- 对前端性能优化(如懒加载、资源裁剪)更有体系化理解
✅ 二、前端工程化与构建优化
6. 前端工程化上有什么方案解决吗,有哪些流程标准或者规范吗
我们采用了以下工程化方案:
- 使用 monorepo + pnpm workspace 管理多个模块
- 自动化构建:Vite/Webpack + GitHooks + CI
- 代码规范:ESLint + Prettier + Commitlint + Husky
- 分支规范:采用 GitFlow
- 自动部署:GitLab-CI + Docker
- 单元测试:Vitest / Jest + Vue Testing Library
7. git merge 有多少种形式(裂)
常见的 merge 形式有:
- 普通合并(merge commit):保留历史,生成新的commit(
git merge
默认行为) - 快进合并(fast-forward):如果目标分支在源分支之后,没有分叉,可以直接指向源(
git merge --ff-only
) - squash 合并:将一组提交压缩成一个提交(
git merge --squash
) - rebase 合并:不是 merge,但常用于“线性合并”流程中(
git rebase
)
8. 对 Webpack 的优化
- 使用
splitChunks
拆分第三方库 - 配置 cache-loader / thread-loader / babel cache
- 启用 tree-shaking
- 使用 CDN 引入大库
- 开启 source-map 选择性(生产关闭或设为 cheap)
- 使用 image-webpack-loader 对图片压缩
- 减少构建体积:alias / externals / dynamic import
9. webpack 构建慢,怎么分析并解决
分析手段:
- 使用 webpack-bundle-analyzer 查看包体大小
- 查看 loader 配置是否重复执行或未命中规则
- 检查是否配置了 缓存机制
- 是否开启了 过多的 sourceMap
- 使用 profiling 模式输出性能数据
优化方法:
- loader 缓存 (
cache: true
) - exclude node_modules 避免不必要编译
- 利用 thread-loader / happyPack 并行构建
- 拆分构建任务:DLLPlugin、ModuleFederation
10. 怎么拆包,比如Vue、Router等公共库?
- 利用 Webpack 的 externals 配置,将 Vue、Vue-Router 等从打包中剔除,通过 CDN 引入
- 使用 splitChunks 拆分第三方库
- 使用 动态 import 按需加载某些模块
- 使用 Vite 的 预构建优化(pre-bundling)
✅ 三、Vue相关
11. Vuex 的理解
Vuex 是一个 集中式状态管理模式,包括:
- state:响应式数据
- mutations:同步修改
- actions:异步操作
- getters:派生状态
- modules:模块化拆分
优点:
- 数据集中、易调试
- 和Vue的响应式系统深度集成
13. Vue2 vs Vue3 响应式的差异与优劣
特性 | Vue2 | Vue3 |
---|---|---|
响应式实现 | Object.defineProperty | Proxy |
数据追踪 | 静态,需预定义 | 动态,可新增属性追踪 |
性能 | 更重,嵌套数据不友好 | 更轻,代理更灵活 |
兼容性 | IE支持好 | IE不兼容Proxy |
Vue3优点:性能更好,类型支持更强,组合式API更易维护
Vue2:老项目兼容性更强
14. 响应式性能差异
Vue3 使用 Proxy 拦截整对象,更适合深层次数据变更和频繁响应;
Vue2 的 defineProperty 每个属性需单独劫持,嵌套结构性能下降严重。
✅ 四、图形与动画
15. Proxy 兼容性
- Proxy 在 IE 全系不支持
- 主流现代浏览器支持良好
- 若需要兼容IE,需降级为Vue2或使用 polyfill(但不完全可靠)
16. Flowable 底层原理
Flowable 是基于 BPMN 2.0 的流程引擎,核心:
- 使用 XML 描述流程图结构
- 前端解析为流程图,后端保存为BPMN模型
- 事件驱动执行流程(节点、网关、事件)
- 支持任务状态流转,配合数据库保存状态机
17. 流程编辑功能支持什么能力
- 拖拽添加任务/分支/网关
- 自定义节点属性
- 连接线逻辑控制
- 校验流程合法性
- 导出/导入 BPMN
18. 是用SVG画的还是Canvas?区别?
我们使用的是 SVG(基于BPMN-js)。
区别:
- SVG:基于DOM,易交互,适合静态图
- Canvas:像素操作,性能好,但事件处理复杂
19. SVG 使用场景
- 图标
- 流程图、组织图
- 矢量图形展示
- 地图覆盖层
20. 实现高帧率JS动画
- 使用
requestAnimationFrame
- 精确控制帧率逻辑(通过时间戳计算)
- 避免 DOM 重排(使用 transform)
- 将计算移出主线程(如 WebWorker)
21. 元素左右移动,减少DOM操作
- 使用 transform: translateX
- 改变 transform 不触发布局重排,仅重绘
- 使用 class 切换样式避免频繁DOM API调用
22. transform 为啥提高性能
- transform 是 合成层(compositing layer)操作
- 不影响其他 DOM 布局,不触发布局回流
- GPU 加速,绘制更流畅
✅ 五、WebSocket、网络协议、加密
23. WebSocket 如何握手
- 客户端发起 HTTP 请求,带有
Upgrade: websocket
请求头 - 服务器返回 101 Switching Protocols
- 握手成功后,建立持久连接
24. WebSocket 协议细节
- 基于 HTTP 1.1 升级协议握手
- 客户端发 Sec-WebSocket-Key,服务端返回Sec-WebSocket-Accept
- 握手完成后进入 WebSocket 协议,开始帧结构传输(opcode, mask等)
25. 后端推送一定要 WebSocket 吗?
不一定:
- WebSocket:双向通信,实时性强
- SSE(Server-Sent Events):服务器单向推送,兼容性好
- 轮询 / 长轮询:兼容广,但效率低
26. SSE 和 WebSocket 区别
特性 | SSE | WebSocket |
---|---|---|
通信方向 | 单向 | 双向 |
协议 | HTTP | 自定义帧结构 |
重连 | 自动支持 | 手动实现 |
兼容性 | 更好 | IE10+ |
用途 | 价格推送、通知 | 聊天、游戏、股票 |
27. WebSocket 文本 vs 二进制
- 文本:适合人类阅读,开发方便
- 二进制:体积小,传输快,适合高频率通信(如视频流)
28. 压缩比例:文本 vs 二进制
- 一般来说:二进制压缩比例更大
- 因为没有编码开销(如Base64),可直接 gzip / deflate
✅ 六、网络协议底层
29. 基于UDP的协议
- DNS
- QUIC(HTTP/3基础)
- DHCP
- TFTP(简单文件传输)
30. DNS解析过程
- 浏览器缓存
- 操作系统缓存
- 本地DNS服务器
- 根域名服务器
- 顶级域名服务器(如 .com)
- 权威域名服务器
- 返回结果并缓存
31. DNS解析优化方法
- 启用 DNS预获取(dns-prefetch)
- 使用 连接池 / HTTP2 多路复用
- 配置 CDN / 域名合并
- 本地 DNS 优化配置
32. TCP多路复用能否优化DNS?
不能直接优化 DNS 查询,但 HTTP2 的多路复用 能减少 DNS 引发的连接数量,从而间接减少耗时
33. keep-alive vs 多路复用
- keep-alive:复用同一TCP连接,但仍是串行
- 多路复用(HTTP2):并行多个请求,提升吞吐
34. HTTP2 特性
- 多路复用
- 头部压缩(HPACK)
- Server Push
- 二进制分帧
35. 头部压缩怎么做(HPACK)
- 利用字典表压缩重复字段
- 编码字段名称和内容为索引编号
- 动态表+静态表组合压缩
36. 压缩算法了解(HPACK)
- HPACK:针对HTTP Header设计的压缩算法
- 结合哈夫曼编码 + 表索引 + 字典动态同步
37. HTTPS 加密过程
- 客户端发起请求(含公钥协商信息)
- 服务端返回证书和加密参数
- 客户端验证证书并生成对称密钥
- 使用公钥加密对称密钥并发送
- 后续使用对称密钥进行通信(更快)
38. 为什么用对称加密?
- 非对称加密安全但慢
- 对称加密速度快,适合大量数据传输
39. XSS 防范
- 输出时转义 HTML 特殊字符(
<
,>
,'
,"
) - 使用 CSP(内容安全策略)
- 防止动态拼接 HTML
- 过滤用户输入内容
✅ 七、算法题
算法 1:带障碍的最短路径
用 BFS 解决,方向为右/下,记录访问过的坐标,时间复杂度 O(m*n)
function shortestPath(grid) {const m = grid.length, n = grid[0].length;const queue = [[0, 0, 0]]; // x, y, stepsconst visited = Array.from({ length: m }, () => Array(n).fill(false));const dirs = [[0, 1], [1, 0]];while (queue.length) {const [x, y, step] = queue.shift();if (x === m - 1 && y === n - 1) return step;for (let [dx, dy] of dirs) {const nx = x + dx, ny = y + dy;if (nx < m && ny < n && !grid[nx][ny] && !visited[nx][ny]) {queue.push([nx, ny, step + 1]);visited[nx][ny] = true;}}}return -1;
}
算法 2:遍历二叉树计算每个节点的和
function computeSums(root) {const result = [];function dfs(node) {if (!node) return 0;const left = dfs(node.left);const right = dfs(node.right);const sum = node.val + left + right;result.push(sum);return sum;}dfs(root);return result;
}
算法 3:去除’b’,以及连续的a和c
function cleanStr(str) {let res = '';for (let i = 0; i < str.length; i++) {if (str[i] === 'b') continue;if ((str[i] === 'a' && str[i + 1] === 'a') || (str[i] === 'c' && str[i + 1] === 'c')) {while (str[i + 1] === str[i]) i++;continue;}res += str[i];}return res;
}