前言
大家好,我是木斯佳。
相信很多人都感受到了,在AI浪潮的席卷之下,前端领域的门槛在变高,纯粹的"增删改查"岗位正在肉眼可见地减少。曾经热闹非凡的面经分享,如今也沉寂了许多。但我们都知道,市场的潮水退去,留下的才是真正在踏实准备、努力沉淀的人。学习的需求,从未消失,只是变得更加务实和深入。
这个专栏的初衷很简单:拒绝过时的、流水线式的PDF引流贴,专注于收集和整理当下最新、最真实的前端面试资料。我会在每一份面经和八股文的基础上,尝试从面试官的角度去拆解问题背后的逻辑,而不仅仅是提供一份静态的背诵答案。无论你是校招还是社招,目标是中大厂还是新兴团队,只要是真实发生、有价值的面试经历,我都会在这个专栏里为你沉淀下来。专栏快速地址

温馨提示:市面上的面经鱼龙混杂,甄别真伪、把握时效,是我们对抗内卷最有效的武器。
面经原文内容
📍面试公司:磐松私募
🕐面试时间:近期
💻面试岗位:27届前端实习一面
📝面试体验:第一次面试,非常紧张,暴露了很多不足
❓面试问题:
- 简单的自我介绍
- rem,vh/vw,媒体查询的区别
- 数组去重如何实现
- 对闭包的理解
- 你的项目中有使用到闭包吗
- webpack和vite区别
- Keepalive有了解吗
- npm,pnpm的区别以及项目中用到了什么
- async,await的本质,以及和promise的关系
- 宏任务微任务执行顺序
- 开始介绍第一个项目
- 问了一下项目中图片处理的算法,没有深入
- 图片上传之后,前后端分别做了什么(这个项目用node.js写的全栈)
- SSE和 WebSocket的区别,为什么没有选择WebSocket
- 如何处理SSE断线重连,数据重复,取消SSE(重复不太清楚,说了数据不完整的解决方法)
- 接入大模型后用没有用到prompt进行限制
- JWT登录流程
- token存储在哪里,存储到本地安全性不高你有没有想过后续优化
- 大文件上传从68%提升到98%,如何测算的
- 上传的格式有没有要求
- 路由懒加载、图片懒加载如何实现的
- 新消息自动滑动如何实现的
- 图片存在哪里
- 介绍第二个项目(问了用的什么模型,是否有prompt限制)
- fetch请求和原生请求的区别
- 项目有没有遇到过内存泄漏
- 计时器使用后的处理方式,在哪个时期销毁的
- 数据库设计
- 如果图片上传速度慢,你会怎么排查
- 有没有了解过我们公司
- 上级或者老师代码意见不同怎么办
- 完成需求和写好代码哪个更重要
- 有没有用过ai辅助,用的cursor的那个大模型
- 需求不清楚如何推进工作流程
- 对这次实习有什么期待吗
- 入职时间
- MBTI
- 期望薪资
- 反问
来源:牛客网 小zhao不吃鱼
💡 木木有话说(刷前先看)
磐松私募的面试挺系统性的,算近期质量不错的实习面了。
📝 磐松私募前端实习一面·深度解析(上)
🎯 面试整体画像
| 维度 | 特征 |
|---|---|
| 面试风格 | 基础全面型 + 项目深挖型 + 场景追问型 |
| 难度评级 | ⭐⭐⭐(三星,基础为主,偶有细节追问) |
| 考察重心 | CSS单位、JS基础(闭包/事件循环)、打包工具、SSE、JWT、懒加载、项目细节 |
| 特殊之处 | 27届首次面试,问题覆盖广但深度适中,适合新手自查 |
🔍 逐题深度解析(上)
二、rem、vh/vw、媒体查询的区别
| 单位/方法 | 参照物 | 适用场景 |
|---|---|---|
| rem | 根元素(html)字体大小 | 移动端适配(配合JS动态设置根字体) |
| vh/vw | 视口高度/宽度的1% | 全屏布局、视口相关尺寸 |
| 媒体查询 | 屏幕宽度/高度/分辨率 | 响应式布局,不同断点应用不同样式 |
css
/* rem适配 */
html { font-size: 16px; }
.box { width: 10rem; } /* 160px */
/* vw适配 */
.box { width: 50vw; } /* 视口宽度的50% */
/* 媒体查询 */
@media (max-width: 600px) {
.box { width: 100%; }
}
三、数组去重实现方法
方法1:Set(最简洁)
javascript
const unique = [...new Set(arr)]
方法2:filter + indexOf
javascript
const unique = arr.filter((item, index) => arr.indexOf(item) === index)
方法3:reduce
javascript
const unique = arr.reduce((acc, cur) => {
if (!acc.includes(cur)) acc.push(cur)
return acc
}, [])
四、闭包的理解
定义:函数可以访问其外部作用域的变量,即使外部函数已执行完毕。
javascript
function outer() {
let count = 0
return function inner() {
count++
return count
}
}
const counter = outer()
counter() // 1
counter() // 2
应用场景:防抖/节流、模块化封装、函数工厂
五、项目中使用闭包的场景
示例:防抖函数
javascript
function debounce(fn, delay) {
let timer = null // 闭包变量
return function(...args) {
clearTimeout(timer)
timer = setTimeout(() => fn.apply(this, args), delay)
}
}
六、Webpack和Vite的区别
| 维度 | Webpack | Vite |
|---|---|---|
| 开发环境 | 打包所有模块,启动慢 | 利用ESM不打包,秒启动 |
| 热更新 | 重新打包相关模块 | 只更新变更的模块 |
| 生产打包 | 打包成bundle | 使用Rollup预打包 |
| 配置复杂度 | 高 | 低 |
七、Keep-alive
Vue的<keep-alive>:缓存组件实例,避免重复渲染。
适用场景:标签页切换、列表详情返回缓存。
八、npm和pnpm的区别
| 维度 | npm | pnpm |
|---|---|---|
| 存储方式 | 每个项目独立存储 | 全局存储 + 硬链接 |
| 磁盘占用 | 高 | 低 |
| 安装速度 | 慢 | 快 |
| 幽灵依赖 | 存在 | 不存在 |
九、async/await的本质及与Promise的关系
本质 :async/await是Promise的语法糖。
javascript
// Promise写法
function getData() {
return fetch('/api').then(res => res.json())
}
// async/await写法
async function getData() {
const res = await fetch('/api')
return res.json()
}
关系:async函数返回Promise,await后面跟Promise。
十、宏任务和微任务的执行顺序
顺序:同步代码 → 清空微任务队列 → 执行一个宏任务 → 再清空微任务 → 循环
javascript
console.log('1')
setTimeout(() => console.log('2'), 0)
Promise.resolve().then(() => console.log('3'))
console.log('4')
// 输出:1,4,3,2
十三、图片上传前后端分别做了什么
前端:
- 文件校验(类型、大小)
- 分片上传(大文件)
- 压缩/预览
- FormData封装,发送请求
- 进度展示
后端:
- 接收文件流
- 校验文件
- 存储到服务器/OSS
- 返回访问URL
十四、SSE和WebSocket的区别
| 维度 | SSE | WebSocket |
|---|---|---|
| 方向 | 单向(服务端→客户端) | 双向 |
| 协议 | HTTP | WS/WSS |
| 自动重连 | 内置 | 手动实现 |
十五、SSE断线重连、数据重复、取消处理
断线重连:SSE原生支持,可自定义重连间隔
javascript
const source = new EventSource('/stream')
source.onerror = () => setTimeout(() => new EventSource('/stream'), 3000)
数据重复:使用消息ID去重
javascript
const receivedIds = new Set()
source.onmessage = (e) => {
const { id, data } = JSON.parse(e.data)
if (receivedIds.has(id)) return
receivedIds.add(id)
processData(data)
}
取消SSE :source.close()
十七、JWT登录流程
- 用户登录 → 服务端验证 → 返回JWT token
- 前端存储token(localStorage或cookie)
- 请求头携带:
Authorization: Bearer <token> - 服务端验证token → 返回数据或401
十八、token存储安全性问题与优化
问题:localStorage存储易受XSS攻击
优化方案:
- 使用httpOnly cookie存储refresh_token
- access_token存内存(Vuex/Pinia)
- 配合SameSite=Strict防止CSRF
十九、大文件上传成功率测算
如何测算:统计上传失败次数 / 总上传次数
- 优化前:上传100次,失败32次 → 成功率68%
- 优化后:上传100次,失败2次 → 成功率98%
二十一、路由懒加载、图片懒加载
路由懒加载:
javascript
const Home = () => import('./views/Home.vue')
图片懒加载:
javascript
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target
img.src = img.dataset.src
observer.unobserve(img)
}
})
})
二十二、新消息自动滑动实现
javascript
const scrollToBottom = () => {
const container = document.getElementById('message-list')
container.scrollTop = container.scrollHeight
}
// 新消息时调用
onNewMessage(() => {
scrollToBottom()
})
二十三、图片存储位置
- 前端:临时存储在内存(Blob URL)或IndexedDB
- 后端:存储在服务器本地、OSS(对象存储)、CDN
📚 知识点速查表(上)
| 知识点 | 核心要点 |
|---|---|
| CSS单位 | rem(根字体)、vh/vw(视口)、媒体查询(断点) |
| 数组去重 | Set、filter+indexOf、reduce |
| 闭包 | 函数+外部作用域,防抖/节流/模块化 |
| Webpack vs Vite | 开发环境打包/不打包,HMR效率 |
| keep-alive | 缓存组件,避免重复渲染 |
| npm vs pnpm | 磁盘占用、安装速度、幽灵依赖 |
| async/await | Promise语法糖 |
| 事件循环 | 同步→微任务→宏任务 |
| SSE vs WebSocket | 单向/双向、自动重连 |
| SSE断线重连 | onerror触发重连、消息ID去重 |
| JWT | 登录→token→请求头携带 |
| token安全 | httpOnly cookie + 内存存储 |
| 懒加载 | 路由懒加载、图片IntersectionObserver |
| 自动滚动 | scrollTop = scrollHeight |
📌 最后一句:
磐松私募这场面试,是一面"基础查漏补缺"的镜子。用户第一次面试,紧张、八股不熟、项目细节模糊,暴露了新手常见的问题。但这恰恰是所有前端er的必经之路------第一次面试的目的不是通过,而是发现自己哪里不会。能清晰记录下这些问题并复盘,已经比大多数原地踏步的人强了。下篇我们将继续解析剩余问题(fetch请求、内存泄漏、计时器销毁、数据库设计、上传慢排查等)。