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

前言

大家好,我是木斯佳。

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

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

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

面经原文内容

📍面试公司:bilibili

🕐面试时间:近期,用户上传于2026-03-26

💻面试岗位:前端一面

⏱️面试时长:45分钟

📝面试体验:未提及

❓面试问题:

  1. 为什么选择学习前端
  2. 你有说到前端技术更新迭代较快,那么平时你都是在哪些平台知道新技术以及学习这些新技术?
  3. html5语义化标签
  4. 是否了解meta,作用是什么?
  5. 对于搜索引擎,meta对他有什么帮助?
  6. 如何实现一个不知高宽的按钮的水平居中,你知道几种方法?
  7. html5中如何实现0.5的边框?
  8. 什么是js闭包以及使用场景?
  9. eventLoop流程?核心解决什么问题?
  10. 有哪些常见的宏任务以及微任务?
  11. vue2你了解么?了解多少?
  12. SSE是什么?和websocket的区别?
  13. SSE的数据格式。
  14. 跨域问题的解决方式和原理?
  15. localStorage,sessionstorage,cookie的区别
  16. sessionStorage存贮了一些数据,如果刷新了页面还存在吗?(存在)
  17. localstorage存储上线只有4mb,如果存满了,还需要存储,应该怎么办(LRU/indexDb)
  18. 强缓存和协商缓存?

两道编程题

一、用promise实现图片的懒加载

二、用promise实现一个红绿灯交替实现,红灯3s,黄灯1s,绿灯3s。

来源:牛客网 胡L1104

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

bilibili这场感觉难度不大,题目中规中矩,相对基础,编程题手撕的话需要准备,其他的还好。


📝 bilibili前端一面·深度解析

🎯 面试整体画像

维度 特征
面试风格 基础扎实型 + 细节追问型 + 实战编程型
难度评级 ⭐⭐⭐(三星半,基础全面,编程题有区分度)
考察重心 HTML/CSS基础、JS核心(闭包/事件循环)、网络与存储、Promise异步编程
特殊之处 两道Promise编程题,既考基础又考实际编码能力

🔍 逐题深度解析

一、为什么选择学习前端

回答思路 :参考上一篇腾讯面经的第一题解析。重点是展现兴趣起源 + 能力匹配 + 价值认同 + 持续学习

加分点:结合bilibili的业务特点,可以说"bilibili是一个内容社区,前端在其中承担着内容呈现和用户交互的核心角色,我希望能用技术让好内容被更多人看见"。


二、学习新技术的平台

回答思路 :面试官在考察你的学习能力和信息获取渠道

推荐回答

  • 技术资讯:掘金、前端之巅、Medium、Twitter(关注尤雨溪、Dan Abramov等)
  • 系统学习:MDN、现代JavaScript教程、React/Vue官方文档
  • 视频课程:bilibili(正好是面试公司)、YouTube(Fireship、The Net Ninja)
  • 实践验证:写demo、参与开源、做side project

加分点:提到"看完文档或教程后,我会自己动手实现一个最小demo,这样理解更深"。


三、HTML5语义化标签

回答思路:说出常见语义化标签及其作用。

核心标签

  • <header>:页眉
  • <nav>:导航
  • <main>:主要内容
  • <article>:独立内容
  • <section>:章节
  • <aside>:侧边栏
  • <footer>:页脚

作用

  1. SEO:搜索引擎更准确识别内容结构
  2. 可访问性:屏幕阅读器更好理解页面
  3. 可维护性:代码结构清晰,便于团队协作

四、meta标签及作用

回答思路 :meta提供HTML文档的元数据,位于<head>中。

常见meta

html 复制代码
<!-- 字符编码 -->
<meta charset="UTF-8">

<!-- 视口设置(移动端适配) -->
<meta name="viewport" content="width=device-width, initial-scale=1">

<!-- 页面描述(影响SEO) -->
<meta name="description" content="页面描述">

<!-- 关键词(SEO权重已降低) -->
<meta name="keywords" content="关键词1,关键词2">

<!-- 作者 -->
<meta name="author" content="作者名">

<!-- 机器人爬虫规则 -->
<meta name="robots" content="index,follow">

对搜索引擎的帮助description会作为搜索结果摘要;keywords(已弱化)曾用于关键词匹配;robots控制爬虫行为。


五、不知高宽的按钮水平居中(多种方法)

回答思路:面试官想考察CSS居中的多种实现方案。

方法1:flex(推荐)

css 复制代码
.container {
  display: flex;
  justify-content: center;
}

方法2:text-align(内联元素)

css 复制代码
.container {
  text-align: center;
}
.button {
  display: inline-block;
}

方法3:绝对定位 + transform

css 复制代码
.container {
  position: relative;
}
.button {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}

方法4:margin: 0 auto(块级元素需定宽)

对于不知宽高的按钮不适用,但可以结合display: tabledisplay: inline-block


六、HTML5中实现0.5px边框

回答思路:高清屏上1px物理边框在CSS中通常显示为2px,需要特殊处理。

方案1:transform: scale

css 复制代码
.half-border {
  position: relative;
}
.half-border::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 1px;
  background: #000;
  transform: scaleY(0.5);
  transform-origin: 0 0;
}

方案2:viewport + rem

html 复制代码
<meta name="viewport" content="width=device-width, initial-scale=0.5, user-scalable=no">

但会影响全局缩放,不推荐。

方案3:box-shadow

css 复制代码
.half-border {
  box-shadow: 0 0.5px 0 0 #000;
}

但兼容性有限。


七、JS闭包及使用场景

回答思路:先解释闭包定义,再说明常见场景。

定义 :函数可以访问其外部作用域的变量,即使外部函数已执行完毕。形成条件是函数嵌套 + 内部函数被引用

javascript 复制代码
function outer() {
  let count = 0
  return function inner() {
    count++
    return count
  }
}
const counter = outer()
console.log(counter()) // 1

使用场景

  1. 封装私有变量(如上面的计数器)
  2. 函数工厂:根据不同参数生成特定功能的函数
  3. 回调函数/事件处理:保存状态
  4. 防抖/节流:保存timer引用
  5. 模块化模式:IIFE创建私有作用域

注意 :闭包会导致内存泄漏,如果不再使用的闭包应手动置null释放。


八、事件循环流程及核心解决的问题

回答思路:参考上一篇腾讯面经的第二题。

核心问题:JavaScript是单线程,需要处理异步操作(定时器、网络请求等),避免阻塞主线程。

流程

  1. 执行同步代码
  2. 遇到异步任务,交给相应API处理
  3. 异步任务完成后,回调进入任务队列(宏任务或微任务队列)
  4. 同步代码执行完,清空微任务队列
  5. 执行一个宏任务,再清空微任务队列,循环

关键:微任务优先级高于宏任务。


九、常见宏任务和微任务

宏任务(MacroTask)

  • setTimeoutsetInterval
  • I/O操作(文件读写、网络请求)
  • UI渲染
  • setImmediate(Node.js)

微任务(MicroTask)

  • Promise.thenPromise.catchPromise.finally
  • MutationObserver
  • queueMicrotask
  • process.nextTick(Node.js)

十、Vue2了解程度

回答思路:诚实回答自己掌握的程度,可以分层次说明。

基础层:响应式原理(Object.defineProperty)、虚拟DOM、模板编译、组件生命周期

API层面:指令(v-if/v-for/v-model)、组件通信(props/emit、事件总线、Vuex)、计算属性/侦听器、插槽

进阶:nextTick原理、keep-alive、mixin混入、自定义指令、render函数

实践经验:可以结合自己做过的项目,说明用Vue2解决了什么具体问题。


十一、SSE与WebSocket的区别及SSE数据格式

回答思路:参考之前AI应用开发面经中关于SSE的详细解析。

SSE数据格式

复制代码
data: 这是一条消息\n\n
data: 第一条消息\n
data: 第二条消息\n\n
event: customEvent\n
data: 自定义事件消息\n\n
id: 12345\n
data: 带ID的消息\n\n
  • data::消息内容,多个data行表示多行消息
  • event::自定义事件类型,前端监听对应事件
  • id::消息ID,断线重连时会发送Last-Event-ID
  • 每条消息以\n\n结尾

客户端示例

javascript 复制代码
const source = new EventSource('/events')
source.onmessage = (e) => console.log(e.data)
source.addEventListener('customEvent', (e) => console.log(e.data))

十二、跨域问题的解决方式和原理

回答思路:先说跨域是什么(同源策略),再说解决方案。

跨域:浏览器安全策略,限制非同源(协议、域名、端口任一不同)的脚本间交互。

解决方案

方案 原理 适用场景
CORS 服务端设置Access-Control-Allow-Origin 最常用,现代Web标准
JSONP 利用<script>不受同源策略限制 仅支持GET,已较少使用
代理转发 同源请求→代理服务器→目标API 开发环境(webpack proxy),生产环境(Nginx)
postMessage 跨窗口通信 iframe与父页面
WebSocket 不受同源限制 实时双向通信

CORS细节:简单请求直接发;非简单请求(PUT/DELETE/自定义头)先发OPTIONS预检。


十三、localStorage、sessionStorage、cookie区别

维度 cookie localStorage sessionStorage
容量 4KB 5-10MB 5-10MB
生命周期 可设置过期时间 永久(手动清除) 标签页关闭即失效
作用域 同源 + 可设置path 同源 同源 + 同标签页
自动携带 是(每次请求)
API 复杂(document.cookie) 简单(setItem/getItem) 简单

十四、sessionStorage刷新后还在吗?

答案存在 。sessionStorage的生命周期是标签页/会话,刷新页面不会清除,只有关闭标签页或浏览器才清除。

追问验证 :可以打开控制台执行sessionStorage.setItem('test', '1'),刷新后执行sessionStorage.getItem('test')验证。


十五、localStorage存满后的处理

回答思路:用户回答"LRU/indexDb",这是正确的方向。

解决方案

  1. LRU(最近最少使用)策略:在应用层实现,存数据时检查大小,超出时删除最久未使用的数据
  2. 使用IndexedDB:容量更大(通常>250MB),支持索引、事务,适合存储大量结构化数据
  3. 分片存储:将大数据拆分成多个key存储
  4. 服务端存储:重要数据不应依赖本地存储
javascript 复制代码
// 简单LRU实现思路
class LRUStorage {
  constructor(limit = 5) {
    this.limit = limit
    this.cache = new Map()
  }
  set(key, value) {
    if (this.cache.size >= this.limit) {
      const firstKey = this.cache.keys().next().value
      this.cache.delete(firstKey)
    }
    this.cache.set(key, value)
  }
  get(key) {
    const value = this.cache.get(key)
    if (value !== undefined) {
      this.cache.delete(key)
      this.cache.set(key, value) // 移到最新
    }
    return value
  }
}

十六、强缓存和协商缓存

回答思路:参考上一篇腾讯面经补充的第六题,此处简要概括。

强缓存 :缓存未过期直接使用,不请求服务器。相关头:Cache-Control: max-age=3600Expires

协商缓存 :缓存过期后向服务器询问,返回304则使用缓存,返回200则更新。相关头:ETag / If-None-MatchLast-Modified / If-Modified-Since

流程图

复制代码
请求 → 检查强缓存 → 未过期 → 使用缓存
                 ↓
               过期 → 发送协商缓存请求 → 304 → 使用缓存
                                   ↓
                                  200 → 更新缓存

编程题一:用Promise实现图片懒加载

题目要求:用Promise实现图片懒加载,即图片进入可视区时才加载。

javascript 复制代码
function lazyLoadImage(imgElement) {
  return new Promise((resolve, reject) => {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          const img = entry.target
          const src = img.dataset.src
          if (src) {
            img.src = src
            img.onload = () => {
              observer.unobserve(img)
              resolve(img)
            }
            img.onerror = () => reject(new Error(`图片加载失败: ${src}`))
          }
        }
      })
    })
    observer.observe(imgElement)
  })
}

// 使用示例
const img = document.querySelector('img[data-src]')
lazyLoadImage(img).then(img => {
  console.log('图片加载完成', img)
}).catch(err => console.error(err))

核心点

  • 使用IntersectionObserver检测可见性
  • 图片真实地址存在data-src属性
  • 加载完成后resolve Promise
  • 支持错误处理

编程题二:用Promise实现红绿灯交替

题目要求:红灯3秒,黄灯1秒,绿灯3秒,循环交替。

javascript 复制代码
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

function red() {
  console.log('红灯亮')
  return sleep(3000)
}

function yellow() {
  console.log('黄灯亮')
  return sleep(1000)
}

function green() {
  console.log('绿灯亮')
  return sleep(3000)
}

async function trafficLight() {
  while (true) {
    await red()
    await green()
    await yellow()
  }
}

// 或者用Promise链式调用
function trafficLight2() {
  red()
    .then(() => green())
    .then(() => yellow())
    .then(() => trafficLight2())
}

// 启动
trafficLight()

核心点

  • 封装sleep函数返回Promise
  • 每个灯返回Promise,用await.then()串联
  • 循环执行

面试官可能的追问 :如何停止循环?可以用一个标志位控制while循环。


📚 知识点速查表

知识点 核心要点
学习平台 掘金、MDN、bilibili、GitHub、官方文档
语义化标签 header/nav/main/article/section/aside/footer,SEO+可访问性
meta标签 charset/viewport/description/robots
水平居中 flex、text-align、绝对定位+transform
0.5px边框 transform:scaleY(0.5)、box-shadow
闭包 函数+外部作用域引用,封装私有变量、函数工厂
事件循环 同步→清空微任务→一个宏任务→循环
SSE 单向、HTTP协议、data格式、自动重连
跨域 CORS、JSONP、代理、postMessage
存储 cookie(4KB/自动携带)、localStorage(永久)、sessionStorage(标签页)
缓存 强缓存(Cache-Control)、协商缓存(ETag/Last-Modified)
LRU 最近最少使用淘汰策略,可用于localStorage满时
Promise懒加载 IntersectionObserver + Promise
Promise红绿灯 sleep + async/await或Promise链

📌 最后一句:

bilibili这场一面,考察的是前端工程师最核心的基础硬实力 。从HTML语义化到CSS布局细节,从JS闭包到事件循环,从网络存储到缓存策略,最后两道Promise编程题,每一题都在检验你是否具备"扎实的前端基本功"。前端技术日新月异,但底层原理和核心能力,永远是安身立命的根本。

相关推荐
吴声子夜歌2 小时前
TypeScript——BigInt、展开运算符、解构和可选链运算符
前端·javascript·typescript
Muen2 小时前
Swift多线程方案-Concurrency
前端
Trouvaille ~2 小时前
【优选算法篇】队列与宽度优先搜索(BFS)——层层递进的视野
c++·算法·leetcode·青少年编程·面试·蓝桥杯·宽度优先
floret. 小花2 小时前
Vue3 知识点总结 · 2026-03-27
前端·面试·electron·学习笔记·vue3
一拳不是超人3 小时前
前端转全栈:你必须要掌握的 Docker 知识
前端·docker·全栈
C澒3 小时前
微前端容器标准化:接入指南
前端·架构
LXXgalaxy3 小时前
Uni-app 小程序页面跳转带参实战笔记(含对象传参与防坑)
开发语言·前端·javascript
2301_768350233 小时前
Vue指令修饰符
前端·javascript·vue.js
oi..3 小时前
Flag和JavaScript document有关
开发语言·前端·javascript·经验分享·笔记·安全·网络安全