字节跳动-字节云-豆包前端实习-一面
时间:一面11.24.25
1 面试流程
- 自我介绍
- 提问
- 编代码
- 向面试官提问
2 面试内容(提问、代码与反向提问)
提问
- 绝对定位和相对定位
- 弹性布局
- flex:1是什么意思
- 原始值的种类(7种)
- GET与POST的区别
- http协议的其他请求方法
- 浏览器的同源策略
- 反向代理是什么
- cookie与session
- git中的rebase和merge
- 移动端优先的设计理念
- 为什么选择Vue3作为技术栈
- 为什么要节流,以及其定义
代码
涉及测试用例的编写,以及怎么保证函数能够通过测试
- 节流函数
- 冒泡排序原理及代码 这部分有一个问题:一个排序函数要输入一个值,如果输入的不是一个数组,那我把它判断出来之后该怎么处理,我应该返回什么,还是应该报错?
- 数组去重
提问
- 团队的技术选型的考量
- AI与低代码平台对前端的影响
- 团队对新人与实习生的帮助
3 复盘反思
首先基础的概念我记得不太清了,针对弹性布局和相对定位这些基础的内容我回答的不够完美。其次是算法设计与一些API的编写,我几乎都忘干净了,尤其是针对节流和防抖的内容。git也是。
据我分析,这个团队的技术栈应该不会包括Vue生态,而是React,因为他表示React的上限更高,对于Vue相关的内容的提问是没有的,如果我有React生态的技术栈,那就该拷打我的这部分了。
全部集中于基础,内容较学院派。要针对简历上的内容进行针对性的复习。对于个人经历部分,我的自我介绍应该是有些简单了,但是面试官也没问,应该也就是不重要。
整体上来讲,能答的都答了,除了表述的不够严谨,本质上也都是回答出来了。我个人认为还算是一次可以满分10分,打6.5分的这么一次面试,勉勉强合格?
4 参考答案
1. 绝对定位和相对定位
相对定位(relative):
- 元素相对于自身正常位置进行定位
- 不会脱离文档流,原位置仍保留
- 通过 top、right、bottom、left 属性调整位置
绝对定位(absolute):
- 元素相对于最近的已定位祖先元素进行定位
- 脱离文档流,不占据原空间
- 如果没有已定位祖先,则相对于初始包含块(通常是视口)
2. 弹性布局
弹性布局(Flexbox)是一维布局模型,用于在容器内高效分配空间和对齐项目。
主要特性:
display: flex创建弹性容器- 主轴(main axis)和交叉轴(cross axis)
- 灵活的项目大小调整和对齐控制
- 响应式设计友好
3. flex: 1 是什么意思
flex: 1 是 flex-grow: 1、flex-shrink: 1、flex-basis: 0% 的简写:
flex-grow: 1:项目可以伸展占用剩余空间flex-shrink: 1:项目可以收缩防止溢出flex-basis: 0%:项目在分配多余空间前的初始大小
4. 原始值的种类(7种)
JavaScript 的 7 种原始数据类型:
undefinednullbooleannumberstringsymbol(ES6)bigint(ES2020)
5. GET 与 POST 的区别
| 特性 | GET | POST |
|---|---|---|
| 安全性 | 参数在URL中,不安全 | 参数在请求体中,相对安全 |
| 数据长度 | 有限制(URL长度限制) | 无限制 |
| 缓存 | 可被缓存 | 不会被缓存 |
| 幂等性 | 幂等(多次请求结果相同) | 非幂等 |
| 用途 | 获取数据 | 提交数据 |
6. HTTP 协议的其他请求方法
- PUT:替换目标资源
- DELETE:删除资源
- HEAD:获取响应头,不返回响应体
- OPTIONS:描述目标资源的通信选项
- PATCH:对资源部分修改
- TRACE:回显服务器收到的请求
7. 浏览器的同源策略
同源策略限制不同源的文档或脚本之间的交互。同源要求:
- 协议相同
- 域名相同
- 端口相同
跨域解决方案:CORS、JSONP、代理服务器等。
8. Cookie 与 Session
Cookie:
- 存储在客户端
- 大小限制约4KB
- 每次请求自动携带
- 安全性较低
Session:
- 存储在服务器端
- 无大小限制
- 通过Session ID识别
- 安全性较高
9. Git 中的 rebase 和 merge
merge:
- 保留分支历史,创建新的合并提交
- 历史记录更完整但可能复杂
rebase: - 将分支基础重置到另一分支
- 历史记录更线性整洁
- 会重写提交历史

10. 移动端优先的设计理念
移动端优先(Mobile First)设计理念:
- 先为移动设备设计,再扩展到桌面端
- 关注核心内容和功能
- 考虑移动设备性能限制
- 渐进增强策略
11. 为什么选择 Vue3 作为技术栈
Vue3 的优势:
- 更好的性能:使用Proxy实现响应式,优化虚拟DOM
- 组合式API:更好的逻辑复用和代码组织
- 更好的TypeScript支持
- 更小的包体积:Tree-shaking优化
- 新的特性:Teleport、Suspense等
12. 为什么要节流,以及其定义
为什么需要节流:
- 防止高频事件(如scroll、resize、input)过度触发
- 减少不必要的函数执行,提升性能
- 避免浏览器卡顿
节流定义: 在规定时间内,函数只能执行一次。如果在此期间再次触发,会被忽略。
字节跳动-字节云-豆包前端实习-二面
时间:11/27/25 时长:1h
1 内容
- 自我介绍
- 提问
- 代码
- 反问
2 提问(32个问题)
你的开源项目是什么呢
你什么时候开始接触前端
之前有过实习呢
学前端你都做了什么呢
在github上的具体项目贡献
项目的来源?
修了哪些Bug呢?
pr与issue的个数
介绍自己的一个项目,具体做了什么呢,怎么实现的呢
什么是SPA?
你的前端路由是怎么设计的呢?
一刻的技术栈?
去看一刻有多少个路由?
看看localstorage的内容
介绍深岩智测的项目
深岩的数据是哪里来的
用了哪些技术栈
有多少个图表,什么样的?
这些图的算法
你掌握的前端知识点有哪些?
浏览器渲染原理
浏览器有多少线程呢
一个页面会有多少线程呢?
有没有事件线程呢,点击鼠标和键盘事件
你了解事件循环机制吗
微任务与宏任务有什么区别呢
平时在用什么AI呢,学习中,开发中有没有用到呢
对于使用AI开发过程中遇到的问题
你要怎么向AI沟通与提问他生成的代码才会更好
你了解哪些AI了解呢
在和AI对话的过程中,AI发生了错误,但你“越聊越错”,对于这种现象是什么原因呢
为什么无法进行纠错,“越聊越正确”呢?为什么越聊幻觉越大呢
3 代码
- 防抖节流
- 针对DOM树的diff算法
4 参考答案
以下是针对每个问题的 细致学习版答案,侧重原理拆解、逻辑推导和实际场景,帮你彻底理解核心知识点,而非单纯记结论:
一、浏览器渲染原理(核心流程+关键概念)
浏览器的核心目标是把 HTML/CSS/JS 转化为用户能看到的页面,整个过程分 5个核心步骤,且是“逐步解析+增量渲染”(不是等所有资源加载完才开始):
1. 解析 HTML → 生成 DOM 树(Document Object Model)
- 原理:浏览器按 从上到下的顺序 读取 HTML 字符流,通过“HTML 解析器”将标签、属性、文本等转化为 DOM 节点(树状结构,根节点是
document)。 - 关键细节:
- 遇到
<link rel="stylesheet">:会暂停 HTML 解析,先加载 CSS 并解析(因为 CSS 会影响 DOM 的样式,避免后续重复渲染); - 遇到
<script>:会 阻塞 HTML 解析和 DOM 生成(因为 JS 可能修改 DOM/CSS,浏览器无法预测,只能先执行 JS); - 解决阻塞:
defer(延迟执行,不阻塞 HTML 解析,DOM 加载完后执行)、async(异步加载,加载完立即执行,可能打乱 JS 顺序)。
- 遇到
2. 解析 CSS → 生成 CSSOM 树(CSS Object Model)
- 原理:CSS 解析器将 CSS 规则(内联、内部、外部)转化为树状结构,每个节点存储对应元素的样式属性(如
color、font-size)。 - 关键:CSS 支持“继承”和“层叠”,CSSOM 会计算每个元素的 最终样式(比如子元素继承父元素的
font-family,同名规则按优先级覆盖)。
3. 合并 DOM + CSSOM → 生成渲染树(Render Tree)
- 原理:筛选出“可见元素”,并将 DOM 节点与对应的 CSSOM 样式绑定。
- 过滤规则:
- 隐藏元素(
display: none)不会进入渲染树(visibility: hidden会进入,因为只是不可见,仍占空间); <head>标签及内部元素(除非手动设置可见)会被过滤。
- 隐藏元素(
- 核心:渲染树只包含“要显示的元素+其样式”,是后续布局和绘制的基础。
4. 布局(Layout/Reflow)→ 计算元素位置和大小
- 原理:遍历渲染树,计算每个节点的 几何信息(坐标
x/y、宽高width/height),最终输出“布局树”(Layout Tree)。 - 触发场景:
- 初始渲染(必触发);
- DOM 结构修改(如增删节点、修改
innerHTML); - CSS 样式修改(如
width、margin、display); - 窗口大小变化(
resize事件); - 获取某些属性(如
offsetWidth、scrollTop,会强制刷新布局)。
- 性能影响:布局是“递归过程”(父元素位置变了,子元素也要重新计算),成本较高,应尽量避免频繁触发。
5. 绘制(Painting)→ 将布局树转化为像素
- 原理:浏览器的“绘制引擎”按布局树的几何信息,将元素的样式(颜色、背景、边框等)绘制到屏幕的“像素缓冲区”。
- 触发场景:布局后必触发;仅修改“不影响布局”的样式(如
color、background-color、box-shadow)时,会直接触发绘制(不触发布局)。
6. 合成(Compositing)→ 合并图层并显示
- 原理:浏览器会将绘制后的内容按“图层”拆分(比如视频、动画、
position: fixed元素会单独成层),然后通过 GPU 合并所有图层,最终显示到屏幕上。 - 核心优势:图层独立绘制,修改某一层时不会影响其他层(比如动画用
transform而非top,只会触发合成,不触发布局和绘制,性能极高)。
总结关键链路:
HTML → DOM → CSSOM → 渲染树 → 布局 → 绘制 → 合成 → 屏幕显示
(性能优化核心:减少布局和绘制的触发次数,尽量只触发合成)
二、浏览器有多少线程?(多进程+多线程架构)
首先明确:浏览器是“多进程”架构(每个进程有独立内存空间,互不干扰),而每个进程内部包含多个“线程”(共享进程内存,协同工作)。
1. 浏览器的核心进程(4个核心进程)
| 进程名称 | 作用 |
|---|---|
| 浏览器进程(主进程) | 管理窗口、用户交互(如地址栏输入)、网络请求调度、进程间通信(IPC)。 |
| 渲染进程(标签页进程) | 核心进程!负责页面渲染(HTML/CSS/JS 解析)、执行 JS、处理 DOM 等(每个标签页默认一个,同域名可能合并)。 |
| GPU 进程 | 处理 GPU 加速任务(如 3D 渲染、图层合成、视频播放),避免阻塞渲染进程。 |
| 插件进程 | 运行浏览器插件(如 Flash、Chrome 插件),独立进程防止插件崩溃影响其他进程。 |
2. 渲染进程内的核心线程(重点!前端相关)
渲染进程是前端最关注的,内部包含 5个核心线程(各司其职,协同工作):
| 线程名称 | 作用 | 关键特性 |
|---|---|---|
| JS 引擎线程(V8 线程) | 执行 JS 代码(同步代码)、管理调用栈。 | 单线程!同一时间只能执行一个任务(避免 DOM 冲突),与 GUI 渲染线程互斥。 |
| GUI 渲染线程 | 执行渲染流程(解析 HTML/CSS、生成渲染树、布局、绘制)。 | 与 JS 引擎线程互斥:JS 执行时 GUI 会暂停,GUI 执行时 JS 会暂停(避免样式和 DOM 不一致)。 |
| 事件触发线程 | 管理“事件队列”(如点击、键盘、定时器、AJAX 回调)。 | 独立于 JS 引擎线程,当事件触发时,将回调函数放入事件队列,等待 JS 引擎空闲时执行。 |
| 定时器线程(setTimeout/setInterval) | 管理定时器的计时和触发。 | 独立于 JS 引擎线程(避免 JS 阻塞导致计时不准),计时结束后将回调放入事件队列。 |
| HTTP 请求线程 | 处理 AJAX/fetch 网络请求。 | 独立线程,可同时发起多个请求(浏览器限制同域名最大并发数,一般 6 个),请求完成后将回调放入事件队列。 |
| 这与之前的学习说法有不同 | ||
| 两种说法不一致的核心原因是对渲染进程主线程角色的理解不同: |
- 正确模型中,渲染进程有一个核心主线程,它既是 "JS 引擎线程" 也是 "GUI 渲染线程",二者互斥运行而非并行
- 渲染流水线还包括合成线程和栅格线程等辅助线程,负责渲染的后期阶段,与主线程协同工作
你的模型虽有简化,但对理解 JS 单线程特性和事件循环机制有帮助;正确模型则更准确反映现代浏览器的实际架构,对性能优化和问题排查更有指导意义。
若需深入理解,建议重点掌握:主线程的核心地位、JS 与渲染互斥原则、合成线程与主线程的协作流程。
总结:
- 浏览器整体:进程数 ≈ 标签页数(同域名合并)+ 核心进程(主进程、GPU、插件);
- 单个渲染进程:固定包含 5 个核心线程(JS 引擎、GUI、事件触发、定时器、HTTP 请求),可额外通过
Web Worker创建新线程(见下一个问题)。
三、一个页面会有多少线程?
一个页面(对应一个渲染进程)的线程数 = 核心线程数 + 自定义线程数:
1. 基础线程(必存在):5 个
即渲染进程内的核心线程(JS 引擎、GUI、事件触发、定时器、HTTP 请求),无论页面是否复杂,这 5 个线程都存在。
2. 自定义线程(可选):Web Worker 线程
- 原理:JS 引擎是单线程,但浏览器允许通过
new Worker()创建 后台线程(Web Worker),用于执行耗时操作(如大数据计算、复杂逻辑处理)。 - 关键限制:
- 不能操作 DOM/CSS(无
document、window对象),只能通过postMessage与主线程通信; - 不能跨域加载脚本(Worker 脚本必须和页面同域名);
- 数量限制:浏览器对单个页面的 Worker 线程数有上限(一般 20-50 个,避免占用过多资源)。
- 不能操作 DOM/CSS(无
3. 特殊线程(按需创建):
- Service Worker 线程:用于离线缓存、推送通知,属于独立于渲染进程的线程(关联页面,但在后台运行);
- Shared Worker 线程:多个同域名页面可共享的 Worker 线程(跨页面通信)。
四、有没有事件线程?点击/键盘事件的处理流程
不是哥们,到底有没有啊,dp说没有,豆包说有
1. 结论:有!即渲染进程内的「事件触发线程」
事件触发线程是独立于 JS 引擎的核心线程,专门负责管理所有“异步事件”的回调函数,包括:
- DOM 事件(点击、键盘、鼠标移动、滚动等);
- 定时器事件(
setTimeout回调); - 网络事件(AJAX/fetch 回调);
- 其他事件(如
Promise状态变更、MessageEvent)。
2. 点击/键盘事件的完整处理流程(结合事件循环)
以“点击按钮”为例,拆解从触发到回调执行的全链路:
- 事件触发:用户点击按钮,浏览器的“输入设备驱动”捕获到点击事件,传递给浏览器主进程;
- 事件分发:主进程通过 IPC 通信,将事件传递给当前页面的渲染进程;
- 事件冒泡/捕获:渲染进程的 DOM 模块先执行事件捕获(从
document向下到目标元素),再执行目标阶段,最后执行事件冒泡(从目标元素向上到document); - 回调入队:事件触发线程找到该事件绑定的回调函数(如
btn.onclick = () => {}),将其放入「事件队列」(宏任务队列); - 等待执行:JS 引擎线程先执行完当前调用栈中的同步代码,空闲后从事件队列中取出回调函数,放入调用栈执行。
关键细节:
- 事件回调的执行时机:必须等 JS 引擎线程空闲(同步代码执行完),所以如果同步代码耗时过长,事件回调会被阻塞(比如点击按钮后,页面卡住几秒才响应,就是因为主线程被同步代码占用);
- 事件委托的原理:利用事件冒泡,将子元素的事件绑定到父元素(如
ul绑定点击事件,处理所有li的点击),本质是事件触发线程在冒泡阶段找到父元素的回调函数。
五、事件循环机制(Event Loop):JS 单线程的异步解决方案
1. 核心前提:JS 为什么是单线程?
- 原因:避免 DOM 冲突(比如一个线程修改 DOM,另一个线程删除 DOM,会导致页面混乱);
- 问题:单线程如果遇到耗时操作(如网络请求、定时器),会阻塞后续代码执行(页面卡住);
- 解决方案:异步任务 + 事件循环(将耗时操作交给其他线程处理,主线程继续执行同步代码,后续再回调)。
2. 事件循环的核心概念
- 同步任务:立即执行的代码(如
let a = 1、fn()),直接进入「调用栈」执行; - 异步任务:不立即执行的代码(如
setTimeout、Promise.then、AJAX),分为两类:- 宏任务(MacroTask):由浏览器/宿主环境触发(如
script整体、setTimeout、setInterval、DOM 事件、AJAX 回调、requestAnimationFrame); - 微任务(MicroTask):由 JS 引擎自身触发(如
Promise.then/catch/finally、MutationObserver、queueMicrotask);
- 宏任务(MacroTask):由浏览器/宿主环境触发(如
- 任务队列:存储异步任务的回调函数,分为「宏任务队列」(多个)和「微任务队列」(一个)。
3. 浏览器环境下的事件循环流程(重点!)
按以下顺序循环执行,直到所有任务完成:
- 执行「调用栈」中的所有同步代码(直到栈空);
- 清空「微任务队列」:将微任务队列中的所有任务按顺序放入调用栈执行(一个都不留);
- 执行一次「宏任务队列」中的第一个任务(注意:只执行一个!);
- 执行完该宏任务后,再次清空「微任务队列」;
- 重复步骤 3-4,直到所有宏任务和微任务都执行完毕。
关键区别:浏览器 vs Node 环境
- Node 环境的事件循环有 6 个阶段(如
timers、poll、check),微任务在每个阶段结束后清空; - 浏览器环境的事件循环更简单:宏任务执行 1 个 → 清空微任务 → 重复。
六、微任务与宏任务的区别(从本质到应用)
| 对比维度 | 宏任务(MacroTask) | 微任务(MicroTask) |
|---|---|---|
| 触发主体 | 浏览器/宿主环境(如 Chrome、Node) | JS 引擎自身(如 V8) |
| 执行优先级 | 低(每个宏任务执行后,必须先清空微任务) | 高(同步代码执行完后,立即清空所有微任务) |
| 队列数量 | 多个(如定时器队列、DOM 事件队列、AJAX 队列) | 一个(所有微任务共用一个队列,按顺序执行) |
| 常见类型 | script、setTimeout、setInterval、DOM 事件、AJAX、requestAnimationFrame | Promise.then/catch/finally、MutationObserver、queueMicrotask |
| 设计目的 | 处理“耗时较长”或“需要宿主支持”的异步操作(如网络请求、定时器) | 处理“短耗时”的异步回调(如 Promise 状态变更),保证数据一致性(避免多次渲染) |
核心原理:为什么微任务优先级更高?
- 微任务通常是“同步操作的后续回调”(如 Promise 执行完后的
then),需要尽快执行,避免数据状态不一致; - 例如:如果微任务和宏任务优先级相同,
Promise.then的回调可能会被setTimeout回调阻塞,导致依赖 Promise 结果的代码出错。
应用场景:
- 微任务:需要“立即执行”的回调(如数据更新后刷新 UI、处理 Promise 结果);
- 宏任务:需要“延迟执行”或“耗时”的操作(如定时器、网络请求、DOM 事件监听)。
七、学习/开发中用到的 AI 工具(前端场景化应用)
1. 学习阶段(侧重“理解知识点”)
- ChatGPT 4o/豆包/通义千问:
- 用途:拆解复杂概念(如事件循环、闭包)、解释报错原因(如“Uncaught TypeError: Cannot read property 'xxx' of undefined”)、对比技术选型(如 Vue3 vs React);
- 示例:“用通俗的语言解释浏览器渲染中的重排和重绘,再举 3 个触发重排的例子”。
- GitHub Copilot X:
- 用途:看开源项目源码时,自动生成注释(理解核心逻辑)、解释陌生 API(如
Intl.DateTimeFormat);
- 用途:看开源项目源码时,自动生成注释(理解核心逻辑)、解释陌生 API(如
- AI 题库工具(如 LeetCode AI 助手):
- 用途:刷算法题时,分析解题思路(如动态规划、贪心)、优化代码(如时间复杂度从 O(n²) 降到 O(n))。
2. 开发阶段(侧重“提高效率”)
- 代码生成/补全:
- GitHub Copilot/Cursor:自动补全重复代码(如表单验证、axios 请求封装)、生成测试用例(如 Jest 测试代码);
- 示例:“用 Vue3 + TypeScript 写一个带分页的表格组件,支持搜索、排序,包含类型定义”。
- 样式生成:
- Tailwind CSS AI:输入自然语言(如“一个圆角、阴影、hover 时放大的按钮,颜色为蓝色”),自动生成 Tailwind 类;
- CSS Scan AI:上传设计图,自动生成 CSS 代码(适配响应式)。
- 错误排查/优化:
- Sentry AI:分析前端报错日志(如生产环境的白屏、卡顿),定位根因(如“内存泄漏源于未清除的定时器”);
- CodeLlama:优化代码性能(如将嵌套循环改为 map 遍历、减少 DOM 操作)。
- 文档生成:
- Documatic:根据代码自动生成 API 文档(如组件的 props、方法说明);
- AI 翻译工具(如 DeepL):翻译英文技术文档(如 MDN、React 官网)。
八、使用 AI 开发过程中遇到的问题(真实场景痛点)
代码有隐藏 Bug(边界条件缺失):
- 示例:AI 生成的“数组去重”代码,没考虑
null、undefined或对象元素(如[1, 2, 2, null, null]去重后漏了null); - 原因:AI 基于训练数据生成,可能忽略小众场景或边界条件。
- 示例:AI 生成的“数组去重”代码,没考虑
代码不符合项目规范:
- 示例:项目要求用 ESLint 规则(如
no-var、indent: 2),但 AI 生成的代码用了var、4 空格缩进; - 原因:AI 不知道项目的具体规范(如命名规范、目录结构)。
- 示例:项目要求用 ESLint 规则(如
过度依赖导致能力退化:
- 场景:基础语法(如
reduce用法、闭包)长期靠 AI 生成,自己记不住核心逻辑,面试时卡壳; - 风险:遇到 AI 无法解决的复杂问题(如框架源码调试),缺乏独立排查能力。
- 场景:基础语法(如
需求理解偏差:
- 示例:要求“React 函数组件的防抖搜索”,AI 生成的是类组件代码,或防抖逻辑写反(
clearTimeout位置错误); - 原因:需求描述不清晰,或 AI 对技术栈的细节理解不足。
- 示例:要求“React 函数组件的防抖搜索”,AI 生成的是类组件代码,或防抖逻辑写反(
性能/安全性问题:
- 性能:AI 生成的代码可能效率低(如用
for循环遍历 DOM 多次,而非documentFragment); - 安全:生成的 AJAX 请求没处理 XSS(如直接将用户输入拼接到 URL)、没验证接口返回数据。
- 性能:AI 生成的代码可能效率低(如用
技术选型过时:
- 示例:生成的 Vue 代码用了
Vue 2的Options API,而项目用的是 Vue 3 的Composition API; - 原因:AI 训练数据有时间滞后,对最新技术(如 Vue 3.4 的新特性)支持不足。
- 示例:生成的 Vue 代码用了
九、如何向 AI 提问,生成更好的代码?(精准提问方法论)
核心原则:给 AI 足够的“上下文+约束+目标”,避免模糊描述,让 AI 知道“要做什么、不能做什么、达到什么效果”。
1. 明确需求场景(含输入/输出)
- 反面示例:“写一个搜索组件”(太模糊,AI 不知道技术栈、功能、样式);
- 正面示例:“React 18 函数组件,实现一个带防抖的搜索输入框:① 输入防抖 500ms;② 输入为空时不发送请求;③ 请求成功后展示结果列表(每一项包含标题和描述);④ 请求失败时显示错误提示(用 Ant Design 的 Message 组件)”。
2. 提供约束条件(技术栈/规范/限制)
- 示例:“用 TypeScript 编写,兼容 ES6+,不使用第三方库(如 lodash),符合 Airbnb ESLint 规范,代码中添加关键逻辑注释”。
3. 给出参考示例(输入/输出/样式)
- 示例:“输入:用户输入‘前端面试’,输出:发送 GET 请求到
/api/search?q=前端面试,响应格式为{ code: 200, data: [{ title: '...', desc: '...' }] },请按这个响应格式处理数据”。
4. 要求解释和优化方向
- 示例:“生成代码后,解释防抖逻辑的核心原理,再说明如何优化这个组件的性能(如缓存请求结果、避免重复渲染)”。
5. 逐步细化需求(迭代式提问)
如果第一次生成的代码不符合预期,精准补充细节,而非重新提问:
- 补充示例:“刚才的代码没有处理请求中断(如用户快速输入时,取消上一次请求),请用 AbortController 实现请求中断,同时添加加载状态(用 Ant Design 的 Spin 组件)”。
6. 避免“开放式提问”,多用“封闭式+细节”
- 反面示例:“这个组件怎么写更好?”;
- 正面示例:“这个搜索组件的防抖逻辑,有没有办法减少不必要的状态更新?请用 useCallback 和 useMemo 优化,并说明优化原因”。
十、了解哪些 AI 工具?(前端分类梳理)
按“功能场景”分类,方便按需选择:
| 功能分类 | 代表工具 | 核心用途 |
|---|---|---|
| 通用问答/学习 | ChatGPT 4o、豆包、通义千问、文心一言 | 技术咨询、概念解释、报错分析、技术选型对比 |
| 代码生成/补全 | GitHub Copilot、Cursor、CodeLlama | 代码补全、组件生成、测试用例编写、开源项目源码解释 |
| 样式/UI 生成 | Tailwind CSS AI、CSS Scan AI、MidJourney | 生成 CSS 代码、设计图转 UI 组件、响应式布局适配 |
| 错误排查/性能优化 | Sentry AI、LogRocket AI、CodeGeeX | 生产环境报错定位、内存泄漏分析、代码性能优化(时间/空间复杂度) |
| 文档/注释生成 | Documatic、CodeWhisperer、AI Code Commenter | 自动生成 API 文档、代码注释、技术文档翻译(英文→中文) |
| 低代码/可视化 | Webflow AI、Mendix AI、AppMaster | 拖拽式开发中生成组件逻辑、适配多端(PC/移动端)、自动生成部署配置 |
| 算法辅助 | LeetCode AI 助手、ChatGPT Code Interpreter | 算法思路分析、代码调试、复杂度优化、生成测试数据 |
关键选型建议:
- 学习/咨询:优先 ChatGPT 4o(逻辑清晰)、豆包(中文支持好);
- 开发/补全:优先 GitHub Copilot(与 VS Code 集成,适配前端技术栈);
- 样式生成:优先 Tailwind CSS AI(与 Tailwind 生态无缝衔接);
- 错误排查:优先 Sentry AI(与前端监控工具集成,适合生产环境)。
十一、AI 越聊越错的原因(从 AI 工作原理拆解)
AI 不是“理解”内容,而是基于 训练数据的统计概率 生成连贯的回答,越聊越错的核心原因是「上下文失真+错误累积」:
上下文窗口限制(最核心原因):
- AI 有“最大上下文长度”(如 GPT-4o 是 128k tokens,约 10 万字),聊得越多,早期的关键信息(如需求、约束、技术栈)会被“遗忘”(超出窗口的信息无法访问);
- 示例:第一次提问时要求“用 Vue3”,聊了 20 轮后,AI 可能忘记,生成 Vue2 代码。
错误累积效应(蝴蝶效应):
- 第一次生成的代码有小错误(如变量名写错),如果没被精准纠正,AI 会把这个错误当成“正确前提”,后续基于错误推导,导致错上加错;
- 示例:AI 第一次把
clearTimeout(timer)写成timer = null(防抖逻辑错误),后续聊“优化防抖”时,会基于timer = null继续修改,越改越错。
模糊的纠错反馈:
- 如果用户只说“不对”“有问题”,AI 无法定位错误点(是语法错?逻辑错?不符合规范?),只能“猜测修改”,可能改对一个地方,又错另一个;
- 反例:“你生成的防抖函数没清除定时器,导致多次触发请求”(精准指出错误点)。
AI 的“迎合性”倾向:
- AI 的训练目标是“生成连贯、符合用户预期的回答”,而非“保证正确性”;
- 如果用户在对话中表现出“误解”(如误以为
setTimeout是微任务),AI 可能顺着用户的误解继续生成内容,而非纠正。
缺乏实时校验能力:
- AI 生成代码时不会实际运行,无法发现运行时错误(如边界条件、异步时序问题);
- 聊得越多,代码逻辑越复杂,AI 越难预判运行时结果,错误率越高。
十二、为什么难以纠错(越聊越正确)?为什么越聊幻觉越大?
1. 为什么难以纠错,做到“越聊越正确”?
核心是「纠错成本远高于初始生成」,需要满足两个前提,而实际中很难做到:
- 前提 1:用户必须 精准理解错误原因(如“防抖函数的定时器清除逻辑错误,因为
clearTimeout应该在每次输入时调用,而不是在回调中”); - 前提 2:用户必须 用 AI 能理解的语言描述错误(避免模糊反馈);
- 现实问题:
- 用户可能自己也没完全搞懂错误原因(比如只知道代码不生效,但不知道为什么);
- 即使精准反馈,AI 可能因上下文窗口限制,忘记之前的约束(如“之前要求兼容 ES6,现在纠正时又用了 ES7 语法”)。
2. 为什么越聊幻觉越大?(幻觉=AI 编造不存在的信息)
AI 的“幻觉”本质是「基于统计概率的“合理编造”」,聊得越多,幻觉越严重的原因:
(1)信息缺口扩大:
- 对话深入后,涉及的细节越来越多(如“这个组件的 props 类型定义、生命周期钩子、与父组件的通信方式”),AI 的训练数据中可能没有对应的“完整信息”;
- 为了生成“连贯的回答”,AI 会基于类似场景“编造”信息(如编造一个不存在的 Vue3 钩子函数、一个不符合规范的 props 类型)。
(2)上下文溢出导致“脑补”:
- 超出上下文窗口后,AI 无法访问早期关键信息,只能基于剩余的碎片化信息“脑补”逻辑;
- 示例:早期要求“用 axios 发请求”,聊到第 30 轮,AI 忘记,编造“用
vue-request库(实际项目没引入),调用useRequest方法”。
(3)训练数据的“模糊边界”:
- AI 对“正确信息”和“错误信息”的判断,基于训练数据中的“出现频率”,而非“事实正确性”;
- 比如小众技术(如某冷门框架的 API)在训练数据中出现次数少,AI 无法区分“正确 API”和“类似 API”,容易编造。
(4)无反馈时的“自我强化”:
- 如果用户没及时纠正第一次的幻觉,AI 会认为“这个编造的信息是正确的”,后续对话中反复使用,幻觉越来越严重;
- 示例:AI 第一次编造“Vue3 的
onMountedAsync钩子(实际不存在)”,用户没纠正,后续聊组件生命周期时,会继续用这个钩子,甚至编造其用法。
总结
以上问题覆盖了前端核心基础(浏览器原理、事件循环、线程模型)和工程实践(AI 工具使用),都是字节二面关注的“深度理解”类知识点。学习时重点抓「原理+实例」:
- 基础部分:用“流程拆解”(如渲染流程、事件循环流程)理解逻辑,用“实例验证”(如代码示例)巩固记忆;
- AI 部分:结合实际开发场景,明确“AI 是工具,不是替代”,重点学习“如何高效利用 AI,同时避免依赖”。
如果某个知识点想进一步深入(如 V8 引擎的事件循环实现、Web Worker 的通信原理),可以随时补充提问!
5 复盘反思
今天二面的效果整体不错,问题出在最后的diff算法,以及人工智能,对于学过的知识已经快遗忘的,我认为说学过,面试官就会追问,反而面试效果不佳,所以学过但是忘了就等于没学就行了。
二面已通过,明天HR面,应该是最后一次了。
另外在思考过程中,眼睛不要向上瞟。 面试官这次提供了一个有趣的说法,日常实习不保证100%的转正机会。
一面考基础,二面深挖项目,太深了太细致了太吓人了,这项目但凡不是自己写的,肯定完蛋(我是自己一个字母一个字母敲上去的😋)
而且这几天的面试官都针对如何使用AI,以及AI相关的内容进行了提问,学习AI十分重要,读研是必要的。
字节跳动-字节云-豆包前端实习-HR面
时间 11/28/25 时长 30min
1 内容
这次忘了录制视频了
- 自我介绍
- 提问
2 提问
大概就是问问理想,你能给企业带来什么价值,诸如此类...
- 你的优缺点
- 你的项目,难点
- 平时用什么AI
- 是否保研?
- 你在带队的过程中所负责的任务,以及最后的成果呢
3 复盘反思
>首先,我认为让一个不懂技术的人来面试我们这些程序员并且还是最后一面,就很有无力感,你没法和她说技术,只能说他能听得懂的。他还觉得你的项目不难啊,我不太满意哈。还觉得我没有实习经历,不懂企业开发的流程,那TM谁一开始就是有经验的,哦都有经验了,谁还投实习,姐们。那你就别一开始找我啊,我简历上不是没写经历吗,那肯定就没有啊,你还来找我干什么。而且,她还迟到了,你是HR,你还迟到
>反正本身我也要去读研,对于读研,实习也不是必要的,你要是喜欢,那就去找你的985吧,我211伺候不了,也不想伺候。我准备学后端了,嘿嘿。
感觉完蛋,真的。感觉自己表现的并不好,没有将自己的全部优势展现出来。
磐松也没有消息,都2天了... 字节的HR面似乎对我也不太满意,这不是又要重新投递啊...
据别人的面经说 >三面结束以后等hr联系,等了很多天都没有等到,3月4日的时候已经心灰意冷,开始准备其他公司的校招了,没想到第二天hr联系我了,超兴奋
可能,就是这样不给你消息的,让你着急。