📝 快手AI应用方向·前端日常实习一面·面经深度解析
前言
大家好,我是木斯佳。
最近感触很深------在AI浪潮席卷之下,前端岗位肉眼可见地变少了,各大社区里的面经分享也没有前几年那么火热了。但我知道,依然有很多同学在努力准备面试,依然需要最新、最真实的前端面试资料。
市场需求在变,但学习的需求一直都在。
为此,我决定开这样一个专栏:专门收集整理最新的前端八股文和真实面经。并在原文基础上,增加面试官角度的问题,而不仅仅是静态的死记硬背。这样无论是校招还是社招,无论是大厂还是中小厂,只要是真实有价值的面试经历,都会在这里沉淀下来。
我发现很多所谓的面经分享都是pdf引流、背后都是培训机构弄的,注意甄别真实性。面试题时效性很重要!!!
面经原文内容
面试公司:快手
🕐面试时间: 1 月 23 日(用户发布时间)
💻面试岗位:前端实习
❓面试问题:
- 1、面试官自我介绍(好评)
- 2、结合项目自我介绍
- 3、项目拷打
- 4、断点续传的实现过程
- 5、vue的响应式原理怎么处理依赖项的(类比react的useEffect)
- 6、项目难点
- 7、怎么看待ai和前端的关系
- 8、日常生活使用哪些大模型,会用来干什么
- 9、希望自己以后的工作状态是怎样的
- 10、算法题
三数之和(老题了) - 11、手写题
用户上传多个图片获得一个blob数组,然后前端调用后端一个API,这个API只能处理一个图片且返回一个图片的URL,确保用户获得的URL地址和上传顺序一致(一开始用class方法写的,写成串行执行的了,后面讲思路类似于promise.all,用index进行保存结果,然后面试官说可以直接用promise.all) - 12、反问
主要技术栈:vue和react都有
怎么看待ai和前端的关系:
ai取代初级前端绰绰有余,前端往全栈方向发展是时代潮流
来源: 牛客网 wowowo
🎯 面试整体画像
| 维度 | 特征 |
|---|---|
| 面试风格 | 闲聊型 + 场景型 + 趋势型 |
| 难度评级 | ⭐⭐⭐(三星,但深度要求高) |
| 考察重心 | AI与前端结合、项目细节、并发控制、技术视野 |
| 典型快手AI风格 | 关注AI工具使用习惯、思考AI对前端的影响、重视工程落地能力 |
🎭 "闲聊"背后的深意
为什么快手AI方向面试喜欢"闲聊"?
| 闲聊话题 | 实际考察点 |
|---|---|
| 日常生活用哪些大模型 | AI工具使用习惯、技术敏感度 |
| 用来干什么 | 解决问题的能力、场景联想能力 |
| 怎么看待AI和前端的关系 | 行业认知、危机感与机遇感 |
| 希望的工作状态 | 职业规划、自驱力、团队匹配度 |
💡 面经关键点:
这不是真的闲聊,是软技能面试 。
AI应用方向的技术更新快,面试官想找的是热爱学习、拥抱变化、有自己思考的人,而不是只会写代码的工具人。
🔄 断点续传·深度解析
问题复盘:
断点续传的实现过程
✅ 完整答案结构(面试官想听的):
1. 核心流程
javascript
// 断点续传 = 分片上传 + 状态记录 + 失败重传
// 第一步:文件分片
const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB
const file = e.target.files[0];
const chunks = [];
for (let start = 0; start < file.size; start += CHUNK_SIZE) {
const end = Math.min(start + CHUNK_SIZE, file.size);
chunks.push(file.slice(start, end));
}
// 第二步:计算唯一标识(文件指纹)
const fileHash = await calculateHash(file); // Web Worker中计算
// 第三步:询问已上传分片
const { uploadedChunks } = await axios.post('/check', {
fileHash
});
// 第四步:上传未完成的分片
const uploadTasks = chunks.map((chunk, index) => {
if (uploadedChunks.includes(index)) {
return Promise.resolve(); // 跳过已上传
}
const formData = new FormData();
formData.append('file', chunk);
formData.append('fileHash', fileHash);
formData.append('chunkIndex', index);
return axios.post('/upload', formData);
});
// 第五步:并发控制上传
await Promise.all(uploadTasks);
// 第六步:通知合并
await axios.post('/merge', { fileHash, fileName: file.name });
2. 关键难点与解决方案
| 难点 | 解决方案 |
|---|---|
| 文件唯一标识 | 计算文件Hash(SparkMD5 + Web Worker) |
| 服务器崩溃 | 记录已上传分片(Redis) |
| 浏览器关闭 | 本地存储上传进度(IndexedDB) |
| 并发数控制 | 实现并发控制器(3-5个并发) |
| 内存占用 | 流式读取 + 分片上传 |
3. 面试官追问方向
追问1:怎么保证文件Hash计算的性能?
javascript
// ✅ Web Worker + 时间切片
const worker = new Worker('hash-worker.js');
worker.postMessage(file);
worker.onmessage = (e) => {
const hash = e.data;
startUpload(hash);
};
// hash-worker.js
self.importScripts('https://cdn.jsdelivr.net/npm/spark-md5');
self.onmessage = (e) => {
const file = e.data;
const spark = new SparkMD5.ArrayBuffer();
const chunks = Math.ceil(file.size / CHUNK_SIZE);
let currentChunk = 0;
const fileReader = new FileReader();
fileReader.onload = (e) => {
spark.append(e.target.result);
currentChunk++;
if (currentChunk < chunks) {
loadNextChunk();
} else {
self.postMessage(spark.end());
}
};
const loadNextChunk = () => {
const start = currentChunk * CHUNK_SIZE;
const end = Math.min(start + CHUNK_SIZE, file.size);
fileReader.readAsArrayBuffer(file.slice(start, end));
};
loadNextChunk();
};
追问2:服务器怎么知道哪些分片已上传?
Redis Hash结构:
fileHash:uploadedChunks→ Set类型存储已上传的chunk索引
追问3:上传过程中断,恢复后怎么避免重复上传?
前端:本地存储已上传分片列表
后端:提供查询接口,返回已接收分片索引
🔍 Vue响应式原理 + 依赖收集(对标React)
问题复盘:
vue的响应式原理怎么处理依赖项的(类比react的useEffect)
✅ 深度对比答案:
1. Vue 3 响应式原理
javascript
// 核心:Proxy + 依赖收集
let activeEffect; // 当前正在执行的effect
class Dep {
constructor() {
this.subscribers = new Set();
}
depend() {
if (activeEffect) {
this.subscribers.add(activeEffect);
}
}
notify() {
this.subscribers.forEach(effect => effect());
}
}
// 响应式对象
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
const dep = getDep(target, key); // 获取属性的依赖收集器
dep.depend(); // 收集当前effect
return target[key];
},
set(target, key, value) {
target[key] = value;
const dep = getDep(target, key);
dep.notify(); // 触发更新
return true;
}
});
}
// effect(相当于watchEffect)
function effect(fn) {
activeEffect = fn;
fn(); // 执行时会触发get,完成依赖收集
activeEffect = null;
}
2. 对标React的useEffect
| 维度 | Vue 响应式 | React useEffect |
|---|---|---|
| 依赖收集 | 自动(运行时追踪) | 手动(显式声明) |
| 更新粒度 | 组件级或更细 | 组件级 |
| 触发时机 | 数据变化立即触发 | 渲染后触发 |
| 实现原理 | Proxy + 发布订阅 | Fiber + 链表比较 |
javascript
// Vue 自动收集
watchEffect(() => {
console.log(count.value); // 自动追踪count
});
// 修改count时会自动执行
// React 手动声明
useEffect(() => {
console.log(count);
}, [count]); // 必须声明依赖
// count变化时执行
3. 面试官追问:为什么Vue可以自动收集,React不行?
Vue是声明式响应系统 :数据是响应式的,天然知道谁用了它
React是函数式不可变:每次渲染都是新快照,无法追踪依赖,必须显式声明
📸 多图上传顺序保证(手写题)
问题复盘:
用户上传多个图片获得一个blob数组,调用后端API(一次只能处理一个),确保URL地址和上传顺序一致
候选人思路:
用index保存结果,类似于Promise.all
✅ 多种解法对比:
解法1:Promise.all(面试官推荐的)
javascript
async function uploadImagesInOrder(images) {
// 并发上传,但保证结果顺序
const uploadPromises = images.map(async (image, index) => {
const url = await uploadSingleImage(image);
return { index, url }; // 携带索引
});
const results = await Promise.all(uploadPromises);
// 按原顺序排序
results.sort((a, b) => a.index - b.index);
return results.map(r => r.url);
}
解法2:顺序执行(你一开始写的)
javascript
async function uploadImagesSequential(images) {
const urls = [];
for (const image of images) {
const url = await uploadSingleImage(image);
urls.push(url);
}
return urls; // 天然保序
}
// 缺点:慢,串行执行
解法3:并发 + 预分配数组
javascript
async function uploadImagesParallel(images) {
const results = new Array(images.length); // 预分配数组
const uploadPromises = images.map(async (image, index) => {
const url = await uploadSingleImage(image);
results[index] = url; // 直接按索引赋值
});
await Promise.all(uploadPromises);
return results; // 天然保序
}
性能对比:
| 方案 | 执行方式 | 耗时(3张图,每张1s) | 代码复杂度 |
|---|---|---|---|
| 顺序执行 | 串行 | 3s | 低 |
| Promise.all | 并发 | 1s | 中 |
| 预分配数组 | 并发 | 1s | 低 ✅ |
💡 面经关键点:
面试官说"可以直接用Promise.all"不是否定你的思路,而是告诉你有更简洁的方案 。
用index保存结果是对的,但可以用数组解构更优雅:
javascriptconst urls = await Promise.all(images.map(uploadSingleImage)); // 等等,这样能保证顺序吗? // 能!Promise.all保持输入顺序
🤖 AI与前端的关系·深度思考(发散类题目没有标准答案)
问题复盘:
怎么看待ai和前端的关系
候选人回答:
ai取代初级前端绰绰有余,前端往全栈方向发展是时代潮流
💡 面经关键点:
你的回答是"防御性思维"(害怕被取代),面试官想听的是"进攻性思维"(如何利用AI)。
更好的回答:"AI不会取代前端,但会用AI的前端会取代不用AI的前端。"
📱 大模型使用习惯·考察点
问题复盘:
日常生活使用哪些大模型,会用来干什么
✅ 答案框架:
1. 常见大模型使用清单示例
| 模型 | 用途 | 为什么选它 |
|---|---|---|
| ChatGPT/GPT-4 | 代码生成、Debug | 代码能力强 |
| Claude | 长文阅读、文档理解 | 100K上下文 |
| Copilot | 日常编码 | IDE集成好 |
| 通义千问 | 中文场景 | 免费、中文好 |
| Midjourney | 设计灵感 | 出图质量高 |
2. 具体使用场景
javascript
// 代码场景
- 写正则表达式
- 生成mock数据
- 解释复杂代码
- 重构建议
// 学习场景
- 解释技术概念
- 对比框架差异
- 生成学习路径
// 工作场景
- 写技术文档
- 生成单元测试
- 代码review辅助
3. 使用心得(加分项)
- 知道AI的边界(不适合做架构设计)
- 知道如何提问(给上下文、分步骤)
- 知道如何验证(AI会编造,要测试)
🧮 三数之和·经典题复盘
题目:
三数之和(老题了)
✅ 标准解法:
javascript
function threeSum(nums) {
const result = [];
nums.sort((a, b) => a - b); // 排序
for (let i = 0; i < nums.length - 2; i++) {
// 去重:跳过相同的第一个数
if (i > 0 && nums[i] === nums[i - 1]) continue;
let left = i + 1;
let right = nums.length - 1;
while (left < right) {
const sum = nums[i] + nums[left] + nums[right];
if (sum === 0) {
result.push([nums[i], nums[left], nums[right]]);
// 去重:跳过相同的第二个数
while (left < right && nums[left] === nums[left + 1]) left++;
// 去重:跳过相同的第三个数
while (left < right && nums[right] === nums[right - 1]) right--;
left++;
right--;
} else if (sum < 0) {
left++;
} else {
right--;
}
}
}
return result;
}
面试官可能追问:
- 时间复杂度?O(n²)
- 空间复杂度?O(1)(不计结果数组)
- 如果找最接近target的三数之和怎么改?
- 四数之和呢?
❓ 反问环节·高分问题
候选人反问:
主要技术栈:vue和react都有
可以追问的深度问题:
| 问题类型 | 示例 | 考察点 |
|---|---|---|
| 技术选型 | 同一个项目里Vue和React怎么共存?有没有微前端方案? | 架构视野 |
| AI落地 | 快手AI应用目前主要用AI做什么?有落地案例吗? | 业务理解 |
| 团队协作 | 团队怎么保证Vue和React项目的代码质量统一? | 工程能力 |
| 个人发展 | 实习生有机会参与AI相关的项目吗? | 主动性 |
📌 快手AI应用方向·通关密码
1. AI不是威胁,是杠杆
- ❌ 思维:AI会取代前端
- ✅ 思维:AI让我从重复劳动中解放,专注创造
2. 项目要体现"深度"
- 断点续传:不只是实现,要考虑性能、健壮性、用户体验
- 依赖收集:不只是背八股,要理解设计哲学
3. 工具要体现"思考"
- 用什么大模型不重要,重要的是用它们解决了什么问题
- 面试官想看到的是一个善于利用工具解决问题的人
4. 闲聊时要"有料"
- 希望的工作状态 → 不只是"氛围好",要说"能参与有挑战的项目"
- 怎么看待AI → 不只是"会取代",要说"我会如何利用"
🎁 附:快手AI方向面试复习清单
| 知识点 | 掌握程度 | 重点方向 |
|---|---|---|
| 断点续传 | ⭐⭐⭐⭐⭐ | Web Worker、并发控制、错误恢复 |
| Vue响应式原理 | ⭐⭐⭐⭐ | Proxy、依赖收集、与React对比 |
| 并发控制 | ⭐⭐⭐⭐ | Promise.all、顺序保证、性能对比 |
| 三数之和 | ⭐⭐⭐ | 排序+双指针、去重 |
| AI工具链 | ⭐⭐⭐ | 主流模型、使用场景、边界认知 |
| 技术视野 | ⭐⭐⭐⭐ | AI与前端结合、未来趋势 |
📌 最后一句:
快手AI方向的面试,是一场技术+认知+潜力 的综合考察。
他们不只要一个会写代码的实习生,
他们要一个能和AI一起进化的人 。
闲聊时的那句"你怎么看",其实是在问:
"你准备好迎接未来了吗?"