前端八股文面经大全:字节前端一面(2026-04-03)·面经深度解析

前言

大家好,我是木斯佳。

相信很多人都感受到了,在AI浪潮的席卷之下,前端领域的门槛在变高,纯粹的"增删改查"岗位正在肉眼可见地减少。曾经热闹非凡的面经分享,如今也沉寂了许多。但我们都知道,市场的潮水退去,留下的才是真正在踏实准备、努力沉淀的人。学习的需求,从未消失,只是变得更加务实和深入。

这个专栏的初衷很简单:拒绝过时的、流水线式的PDF引流贴,专注于收集和整理当下最新、最真实的前端面试资料。我会在每一份面经和八股文的基础上,尝试从面试官的角度去拆解问题背后的逻辑,而不仅仅是提供一份静态的背诵答案。无论你是校招还是社招,目标是中大厂还是新兴团队,只要是真实发生、有价值的面试经历,我都会在这个专栏里为你沉淀下来。专栏快速地址

温馨提示:市面上的面经鱼龙混杂,甄别真伪、把握时效,是我们对抗内卷最有效的武器。

面经原文内容

📍面试公司:字节跳动

🕐面试时间:近期

💻面试岗位:前端一面

⏱️面试时长:45分钟

📝面试体验:面试官非常和善,会复述你的回答double check

❓面试问题:

实习项目穿插八股

  1. 登录页面怎么做的
  2. 后端传过来的jwt存在哪里?为什么放在cookie里?放在local storage里怎么携带的?
  3. sessionStorage和localStorage有什么区别
  4. 除了这种缓存还有其他的缓存手段(答了协商缓存、强缓存)
  5. 协商缓存和强缓存下浏览器的请求行为,协商缓存的相关字段+状态码
  6. 大文件上传怎么做的
  7. 为什么要用sse
  8. sse连接断开怎么办
  9. 接口降级方案具体是怎么实现的
  10. 主要观测的性能指标有哪些,LCP是怎么算的,具体LCP数值是多少
  11. 性能优化做了哪些内容
  12. vite和webpack的流程、区别
  13. 技术选型问题,为什么项目开发使用vue3不用react
  14. vue3的响应式
  15. vue编译渲染是怎么做的

coding(3道)

  1. 限制数量的事件调度器(Scheduler)
  2. hot100中的括号生成,问了一下时间复杂度
  3. 两个版本序列号排序问题

来源:牛客网 盐酸不酸

💡 木木有话说(刷前先看)

字节这场一面,是典型的"项目深挖+基础考察+算法"组合。面试官非常友善,会复述你的回答确认理解正确,这种风格下更容易发挥真实水平。尤其值得关注的是"接口降级方案"和"LCP具体数值",考察的是生产环境的实战思维。(最近的题多讲思路,因为重复题比较多,建议大家看汇总篇,根据汇总篇的热点考点去进行专项复习)


📝 字节前端一面·深度解析

🎯 面试整体画像

维度 特征
面试风格 项目驱动型 + 友善沟通型 + 实战追问型
难度评级 ⭐⭐⭐⭐(四星,覆盖面广,算法有区分度)
考察重心 登录鉴权、缓存策略、大文件上传、SSE、性能优化、构建工具、Vue原理、算法
特殊之处 面试官会复述回答确认理解,考察沟通确认能力

🔍 逐题深度解析

一、登录页面怎么做的

回答思路:从表单交互、数据提交、token处理、路由守卫等方面说明。

要点

  • 表单校验(手机号/邮箱、密码格式)
  • 提交时禁用按钮,防止重复提交
  • 调用登录API,获取token
  • token存储(cookie/localStorage)
  • 登录成功跳转,失败展示错误提示
  • 路由守卫:未登录时重定向到登录页

二、JWT存在哪里?为什么放cookie?localStorage怎么携带?

回答思路:对比存储方式的优劣。

存储位置

  • localStorage :需手动在请求头Authorization: Bearer <token>携带
  • cookie :设置httpOnly防止XSS,设置SecureSameSite,请求自动携带

为什么放cookie

  • httpOnly:防止XSS攻击窃取token
  • 自动携带:无需手动处理请求头
  • SameSite:可防范CSRF

localStorage携带方式

javascript 复制代码
// 存储在localStorage
localStorage.setItem('token', token)

// 请求拦截器添加
axios.interceptors.request.use(config => {
  const token = localStorage.getItem('token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
})

三、sessionStorage和localStorage区别

维度 localStorage sessionStorage
生命周期 永久(手动清除) 标签页关闭即失效
作用域 同源 同源+同标签页
容量 5-10MB 5-10MB

四、除了本地存储,还有其他缓存手段

回答思路:用户答了协商缓存、强缓存,正确。

HTTP缓存

  • 强缓存Cache-Control: max-age=3600,缓存期间不发请求
  • 协商缓存ETag/If-None-MatchLast-Modified/If-Modified-Since,返回304则复用

其他:CDN缓存、Service Worker缓存、内存缓存(Memory Cache)。


五、强缓存和协商缓存的请求行为、字段、状态码

强缓存

  • 请求行为:缓存有效期内,不发请求,直接从缓存读取
  • 状态码:200 (from disk cache)200 (from memory cache)
  • 字段:Cache-Control(优先级高)、Expires

协商缓存

  • 请求行为:缓存过期后,发请求验证资源是否变化
  • 状态码:304 Not Modified(资源未变化)或 200(资源更新)
  • 字段:请求头If-None-Match(对应响应头ETag)、If-Modified-Since(对应Last-Modified

六、大文件上传怎么做的

回答思路:核心是分片上传、断点续传、并发控制。

流程

  1. 文件分片:Blob.slice()将文件切分成多个chunk(如每片1MB)
  2. 计算哈希:用spark-md5计算文件哈希,用于秒传判断
  3. 上传分片:并发上传(控制并发数),每个分片带序号
  4. 断点续传:服务端记录已上传分片,前端跳过已上传的
  5. 合并通知:所有分片上传完成后,通知服务端合并
javascript 复制代码
// 分片上传示例
async function uploadFile(file) {
  const chunkSize = 1024 * 1024 // 1MB
  const chunks = Math.ceil(file.size / chunkSize)
  
  for (let i = 0; i < chunks; i++) {
    const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize)
    const formData = new FormData()
    formData.append('chunk', chunk)
    formData.append('index', i)
    formData.append('total', chunks)
    await fetch('/upload', { method: 'POST', body: formData })
  }
  
  // 通知合并
  await fetch('/merge', { method: 'POST', body: JSON.stringify({ fileName: file.name }) })
}

七、为什么要用SSE

回答思路:SSE适用于服务端向客户端单向推送的场景。

AI对话场景

  • LLM生成是服务端→客户端的单向流
  • SSE基于HTTP,实现简单,自动重连
  • 比WebSocket轻量,资源开销小

八、SSE连接断开怎么办

回答思路:SSE原生支持自动重连,但生产环境需做增强。

处理方案

  1. 原生重连 :SSE的EventSource会自动重连
  2. 自定义重试 :监听onerror,实现指数退避重连
  3. 断点续传 :携带Last-Event-ID,服务端从断点继续推送
javascript 复制代码
let retryCount = 0
function connectSSE() {
  const source = new EventSource('/api/stream')
  
  source.onerror = () => {
    source.close()
    const delay = Math.min(1000 * Math.pow(2, retryCount), 30000)
    setTimeout(() => {
      retryCount++
      connectSSE()
    }, delay)
  }
  
  source.onopen = () => { retryCount = 0 }
}

九、接口降级方案具体是怎么实现的

回答思路:降级是高可用设计,当主接口失败时,使用备用方案。

实现方式

  1. 超时降级:设置超时时间,超时后走降级逻辑
  2. 失败降级:主接口报错后,调用备用接口或返回缓存数据
  3. 熔断降级:连续失败N次后,直接走降级,不请求主接口
  4. 限流降级:超出QPS限制时,返回默认数据或友好提示
javascript 复制代码
async function fetchWithFallback() {
  try {
    const response = await fetch('/api/main', { timeout: 3000 })
    return await response.json()
  } catch (error) {
    // 降级:使用缓存或备用接口
    const cached = localStorage.getItem('cachedData')
    if (cached) return JSON.parse(cached)
    
    const fallback = await fetch('/api/fallback')
    return await fallback.json()
  }
}

十、主要观测的性能指标、LCP计算方式与数值

回答思路:核心Web Vitals包括LCP、FID、CLS。

LCP(Largest Contentful Paint) :最大内容绘制时间,衡量加载性能。通过PerformanceObserver观测页面中最大的元素(图片、视频、文本块)渲染完成的时间。

计算方式

javascript 复制代码
new PerformanceObserver((list) => {
  const entries = list.getEntries()
  const lastEntry = entries[entries.length - 1]
  console.log('LCP:', lastEntry.renderTime || lastEntry.loadTime)
}).observe({ entryTypes: ['largest-contentful-paint'] })

数值标准

  • 优秀:≤ 2.5秒
  • 需改进:2.5-4秒
  • 差:> 4秒

十一、性能优化做了哪些内容

回答思路:从加载、渲染、网络多个维度展开。

优化项

  • 代码分割:路由懒加载、动态导入
  • 图片优化:WebP格式、懒加载、响应式图片
  • 资源压缩:JS/CSS压缩、Gzip/Brotli
  • 缓存策略:强缓存、协商缓存、CDN
  • 虚拟滚动:长列表优化
  • 减少重排重绘:用transform/opacity做动画
  • 预加载:preload关键资源、prefetch低优先级资源

十二、Vite和Webpack的流程、区别

维度 Webpack Vite
开发环境 打包所有模块,启动慢 利用ESM,直接启动
热更新 重新打包相关模块 只更新变更的模块
生产打包 统一打包成bundle 使用Rollup预打包
配置复杂度

流程

  • Webpack:入口→依赖解析→loader转换→打包→输出
  • Vite:启动服务器→请求时编译→利用浏览器ESM加载

十三、技术选型:Vue3 vs React

回答思路:结合项目需求说明。

Vue3优势

  • 上手简单,模板语法直观
  • 响应式自动依赖收集,开发效率高
  • 官方生态完善(Vue Router、Pinia)

React优势

  • 灵活度高,适合复杂交互
  • 生态更丰富
  • 函数式编程范式

选型原因:团队熟悉度、项目复杂度、社区生态。


十四、Vue3响应式

回答思路:基于Proxy实现,懒递归。

核心

  • reactive:用Proxy代理对象,拦截get/set/deleteProperty
  • ref:包装基本类型,通过.value访问
  • effect:依赖收集,触发更新
  • 懒递归:只有访问嵌套对象时才代理

十五、Vue编译渲染是怎么做的

回答思路:模板 → AST → 渲染函数 → VNode → 真实DOM。

流程

  1. 解析:将模板字符串解析成AST(抽象语法树)
  2. 转换:对AST进行优化(标记静态节点)
  3. 生成 :生成渲染函数(render函数)
  4. 渲染:执行渲染函数生成VNode
  5. 更新:VNode与旧VNode进行diff,更新真实DOM

Coding题一:限制数量的事件调度器(Scheduler)

题目:实现一个并发限制的调度器,最多同时执行2个任务。

javascript 复制代码
class Scheduler {
  constructor(limit = 2) {
    this.limit = limit
    this.running = 0
    this.queue = []
  }
  
  add(promiseFactory) {
    return new Promise((resolve, reject) => {
      this.queue.push(() => {
        promiseFactory().then(resolve, reject).finally(() => {
          this.running--
          this.next()
        })
      })
      this.next()
    })
  }
  
  next() {
    if (this.running < this.limit && this.queue.length) {
      const task = this.queue.shift()
      this.running++
      task()
    }
  }
}

Coding题二:括号生成

题目:给定n对括号,生成所有有效的括号组合。

javascript 复制代码
function generateParenthesis(n) {
  const result = []
  
  function backtrack(str, left, right) {
    if (str.length === 2 * n) {
      result.push(str)
      return
    }
    if (left < n) backtrack(str + '(', left + 1, right)
    if (right < left) backtrack(str + ')', left, right + 1)
  }
  
  backtrack('', 0, 0)
  return result
}

时间复杂度 :卡特兰数,O(4^n / √n)


Coding题三:版本序列号排序

题目 :对版本号数组进行排序,如['1.0.1', '1.0', '1.0.2', '2.0']

javascript 复制代码
function compareVersion(v1, v2) {
  const parts1 = v1.split('.').map(Number)
  const parts2 = v2.split('.').map(Number)
  const maxLen = Math.max(parts1.length, parts2.length)
  
  for (let i = 0; i < maxLen; i++) {
    const num1 = parts1[i] || 0
    const num2 = parts2[i] || 0
    if (num1 !== num2) return num1 - num2
  }
  return 0
}

function sortVersions(versions) {
  return versions.sort(compareVersion)
}

📚 知识点速查表

知识点 核心要点
登录鉴权 JWT存储(cookie/localStorage)、请求拦截器携带
存储区别 localStorage永久/sessionStorage标签页/cookie自动携带
HTTP缓存 强缓存(Cache-Control/Expires)、协商缓存(ETag/Last-Modified)
大文件上传 分片(Blob.slice)、断点续传、秒传(文件哈希)
SSE 单向推送、自动重连、断线恢复(Last-Event-ID)
接口降级 超时降级、熔断、限流、缓存兜底
LCP 最大内容绘制,≤2.5s优秀,PerformanceObserver获取
性能优化 代码分割、图片优化、虚拟滚动、预加载
Vite vs Webpack 开发环境ESM/打包、热更新机制、生产构建
Vue3响应式 Proxy代理、懒递归、ref包装基本类型
Vue编译 模板→AST→渲染函数→VNode→DOM
调度器 并发限制、任务队列
括号生成 回溯、左右括号数量约束
版本排序 拆分解析、补0对齐

📌 最后一句:

字节这场一面,风格友善但内容硬核。从登录JWT存储、大文件上传,到LCP性能指标、Vue编译原理,再到三道算法题,全面考察了项目实战能力和计算机基础。面试官会复述你的回答double check,这种沟通方式值得学习------确认理解一致,是高效协作的关键。能通过这样的面试,说明你不仅会写代码,更能清晰地表达技术决策。

相关推荐
xiaotao1312 小时前
第八章:实战项目案例
前端·vue.js·vite·前端打包
We་ct2 小时前
JS手撕:性能优化、渲染技巧与定时器实现
开发语言·前端·javascript·面试·性能优化·定时器·性能
taWSw5OjU2 小时前
vue对接海康摄像头-H5player
开发语言·前端·javascript
huwuhang2 小时前
跨平台电子书阅读器 | Readest最新版 安卓版+PC版全平台
android·前端·javascript
C澒2 小时前
AI 生码:RAG 检索优化实现可评估、可回溯工程化
前端·ai编程
条tiao条2 小时前
不止语法糖:TypeScript Set 与 Map 深度解析
前端·javascript·typescript
freewlt2 小时前
React Server Components 深度解析:从原理到实战的完整指南
前端·javascript·react.js
Linux猿3 小时前
AI产品经理面试题65道 | 附PDF
人工智能·面试·产品经理·面试题·面试题目·ai产品经理面试题
ZC跨境爬虫3 小时前
Playwright进阶操作:鼠标拖拽与各类点击实战(含自定义拖拽实例)
前端·爬虫·python·ui