Skip to content

面试随记

AI

“它解决的核心问题,是把我的精力,从重复性和记忆性的工作中解放出来,让我能更专注于创造性和架构性的工作

熟练掌握 Vue3 + TypeScript,具备组件化开发经验,熟悉 Composition API 及常用生态

面试官你好,我是,从事前端开发已经六年了,主要技术栈是 Vue3、TypeScript、UniApp 等
一共任职过两家公司,第一份是毕业到2020年3月,是在郑州从事的外包开发,主要使用uniapp开发app和微信小程序
第二个是在上海,一家自研的流量变现公司,负责前端的所有工作,包括 公司运营的后台管理系统、广告信息流项目以及快应用,微信,支付宝等多个小程序产品
最近也比较关注 AI 与前端结合的应用场景,在项目中也有接入 AI 能力的实践,比如 AI 内容生成和 Prompt 优化等。
希望能加入我们这个新团队,也不断提升自己的技术能力的同时,也能为公司创造实际价值

一、Vue3 高频八股


1️⃣ Vue3 相比 Vue2 的核心升级点是什么?

✅ 标准答案:

  1. 使用 Proxy 替代 Object.defineProperty
  2. 重写虚拟 DOM(PatchFlag + 静态提升)
  3. Composition API
  4. 更好的 Tree Shaking
  5. Fragment / Teleport / Suspense
  6. 更好的 TypeScript 支持

二、Vue3 性能提升(重点)


2️⃣ Vue3 为什么比 Vue2 性能好?

✅ 1. 响应式优化(核心)

Vue2 使用:

js
Object.defineProperty

缺点:

  • 不能监听数组索引变化
  • 不能监听对象新增属性
  • 初始化递归遍历

Vue3 使用:

js
Proxy

优势:

  • 可以监听新增 / 删除属性
  • 可以监听数组索引
  • 惰性代理(访问时才递归)
  • 性能更高

👉 面试加分说法:

Vue3 响应式基于 Proxy + Reflect 实现,采用懒代理机制,避免 Vue2 初始化阶段的深度递归遍历,提高了大型对象的初始化性能。


✅ 2. PatchFlag(虚拟DOM优化)

Vue3 在编译阶段会标记动态节点:

js
<div>{{ msg }}</div>

会被标记为:

js
PatchFlag.TEXT

更新时:

👉 只更新标记的动态节点 👉 不再进行全量 Diff

Vue2:

  • 每次更新都全量对比 VNode

Vue3:

  • 只对动态节点做 Diff

性能大幅提升。


✅ 3. 静态提升(Static Hoisting)

静态节点只创建一次:

html
<div>
  <p>我是静态</p>
  <span>{{ msg }}</span>
</div>

<p> 会被提升到 render 外部。

Vue2 每次 render 都重新创建。

Vue3 只创建一次。


✅ 4. 事件缓存(Cache Handler)

Vue3 默认缓存事件函数:

Vue2:

html
<button @click="handleClick">点击</button>

每次 render 都重新生成函数引用。

Vue3:

会缓存 handler,减少重复创建。


✅ 5. Tree Shaking

Vue3 模块化拆分:

js
import { ref } from 'vue'

只打包用到的 API。

Vue2 是整体打包。


三、Vue3 响应式原理


3️⃣ Vue3 响应式是怎么实现的?

标准回答结构:

  1. reactive 创建 Proxy
  2. 依赖收集 track
  3. 依赖触发 trigger
  4. effect 副作用函数

核心流程:

js
effect(() => {
  console.log(state.count)
})
  • 读取 count → 触发 track 收集依赖
  • 修改 count → 触发 trigger 执行 effect

底层数据结构:

js
WeakMap → Map → Set

四、Composition API 优势


4️⃣ 为什么推荐 Composition API?

标准答案:

  1. 逻辑复用更方便
  2. 避免 mixin 命名冲突
  3. 更清晰的逻辑分组
  4. 更好的 TypeScript 支持
  5. 更适合大型项目

五、JS 八股(必须会)


5️⃣ 闭包是什么?

函数 + 它能访问的作用域环境。

一般是一个函数返回了一个函数的情形,

  1. 返回的函数,仍然可以i访问外层函数的局部变量即使外层函数已经执行结束
  2. 这种访问保持了外层变量的状态,可以实现私有变量或累加器等功能
  3. 并不是所有返回函数的场景都是闭包,关键是返回的函数引用了外层函数的变量

闭包

常见应用:

  • 防抖节流
  • 模块封装
  • 私有变量

6️⃣ 原型链是什么?

对象通过 __proto__ 指向构造函数的 prototype。

查找规则:

对象本身 → prototype → Object.prototype → null


7️⃣ Promise 执行机制

  • 同步代码先执行
  • 微任务(Promise)
  • 宏任务(setTimeout)

事件循环顺序:

Promise.all全部成功才成功
Promise.race谁先结束用谁
Promise.any有一个成功就返回
Promise.allSettled全部执行完,不管成功失败
同步 → 微任务 → 宏任务

六、性能优化(高频)


8️⃣ 前端性能优化手段?

资源层面:

  • 图片懒加载
  • gzip
  • CDN
  • Tree Shaking

代码层面:

  • 防抖节流
  • 虚拟列表
  • keep-alive
  • 组件拆分
  • 路由懒加载

Vue 层面:

  • v-memo
  • v-once
  • 合理使用 computed
  • 避免深层 watch

🎯 最重要:Vue3 性能提升总结模板(必背)

面试回答可直接背:

Vue3 相比 Vue2 性能提升主要体现在三个方面:

第一,响应式系统改为 Proxy,实现惰性代理,解决了 Vue2 无法监听新增属性的问题;

第二,虚拟 DOM 引入 PatchFlag 和静态提升,在编译阶段标记动态节点,更新时只对动态部分进行 Diff;

第三,支持 Tree Shaking,打包体积更小。

整体上 Vue3 在初始化性能、更新性能和包体积方面都有明显提升。


一、Vue3 深度题(社招核心)


1️⃣ Vue3 响应式原理,和 Vue2 有什么本质区别?

✅ 标准结构回答:

Vue3 使用 Proxy + Reflect 实现响应式,相比 Vue2 的 Object.defineProperty 有三个核心提升:

① 监听能力增强

Vue2:

  • 无法监听新增属性
  • 不能监听数组索引
  • 需要重写数组方法

Vue3:

  • Proxy 可以拦截 get / set / deleteProperty
  • 可以监听数组索引变化
  • 可以监听属性新增删除

② 性能优化(重点说)

Vue2 初始化时会递归遍历对象,深度劫持。

Vue3 是 懒代理机制

只有在访问对象时才进行递归代理

减少初始化性能消耗。


③ 数据结构优化

依赖收集结构:

WeakMap
  └─ Map
      └─ Set
  • target → key → effect

WeakMap 防止内存泄漏。


🎯 面试追问点

  • effect 是怎么避免死循环的?
  • ref 和 reactive 区别?
  • computed 为什么有缓存?

2️⃣ Vue3 性能优化点(必背完整版)

你可以这样回答:

Vue3 性能提升主要来自三方面:响应式优化、编译优化、打包优化。


① 响应式优化

  • Proxy 替代 defineProperty
  • 惰性代理
  • 更精准的依赖追踪

② 编译阶段优化(这是社招重点)

PatchFlag

Vue3 在编译阶段标记动态节点:

html
<div>{{msg}}</div>

会被标记为 TEXT 类型。

更新时:

只更新动态节点,不再全量 diff


静态提升(Static Hoisting)

静态节点只创建一次。

Vue2 每次 render 都重新创建。


事件缓存

Vue3 会缓存事件函数引用,减少 render 过程中函数重新创建。


③ Tree Shaking

Vue3 API 按需引入,减少包体积。


🎯 加分回答

Vue3 通过“编译时优化”减少运行时计算,这是本质区别。


3️⃣ Composition API 为什么更适合大型项目?

社招要回答“痛点”。

Vue2 痛点:

  • 逻辑分散在 data、methods、computed
  • mixin 命名冲突
  • 逻辑复用困难

Vue3 优势:

  • 按功能组织代码
  • 更好的逻辑复用
  • 更好 TypeScript 推导
  • 更利于拆分业务模块

二、真实项目场景题(社招必问)


4️⃣ 你做过哪些 Vue 性能优化?

你可以这样答(模板):

在项目中我主要做过以下优化:

  1. 使用路由懒加载减少首屏加载体积
  2. 使用 keep-alive 缓存列表页
  3. 大数据列表使用虚拟滚动
  4. 避免不必要的深层 watch
  5. 合理拆分组件,减少重复渲染
  6. 图片懒加载 + CDN

如果你做过视频项目,可以加:

对大图和视频做了压缩与分片加载优化。


三、JS 深度八股(社招必问)


5️⃣ 事件循环机制

必须能画流程:

同步任务

微任务(Promise)

宏任务(setTimeout)

追问:

  • async await 本质?
  • nextTick 属于什么?

6️⃣ 防抖和节流区别

防抖:

触发后延迟执行。事件持续触发时,只在最后一次触发后执行(多用于输入框)

节流:

固定时间执行一次。(多用于按钮)

追问:

  • 立即执行版本怎么实现?
  • Vue 场景怎么用?
GET 是幂等
POST 不是
PUT 是幂等
DELETE 是幂等

四、工程化(社招必问)


7️⃣ Vite 为什么快?

标准答案:

  • 基于 ES Module
  • 开发阶段不打包
  • 按需加载
  • 使用 esbuild 预构建

8️⃣ 你如何做打包优化?

  • 分包
  • 代码分割
  • CDN 外链
  • gzip
  • Tree Shaking
  • 图片压缩

五、Node 基础(你必须准备)


9️⃣ Express 中间件原理?

函数链模型:

(req, res, next)

通过 next 控制流程。


🔟 MySQL 索引原理?

  • B+ 树
  • 主键索引
  • 联合索引最左匹配原则

六、社招最容易挂的题


❓ watch 和 computed 区别?

computed:

  • 有缓存
  • 基于依赖自动更新
  • 适合计算属性

watch:

  • 监听变化
  • 执行副作用

❓ ref 和 reactive 区别?

  • ref 用于基本类型
  • reactive 用于对象
  • ref 本质也是 reactive 包装

对比点
存储内容基本类型 / 引用地址对象 / 数组
空间大小
分配方式自动分配动态分配
访问速度相对慢
生命周期由函数调用决定由 GC 决定

JS 常见垃圾回收机制

1️⃣ 引用计数(早期)

原理:

每个对象有一个引用次数 引用 +1 解除引用 -1 当为 0 时回收

2️⃣ 标记清除(现代主流)

现在主流浏览器都用这个。

原理:

  1. 从根对象(window / global)开始遍历
  2. 能访问到的标记为“存活”
  3. 不能访问到的标记为“垃圾”
  4. 清除未标记对象

优点:

✅ 能解决循环引用问题

面试问答

一线城市和二三线城市,通过ip定位获取当前的定位区域,然后配置不同的广告策略

配置的有奖励的三篇30s等,visibilitychange的监听,有的是和app合作,有的是自己页面对接的支付宝提现,
根据第二天广告后台的收益反馈,进行业务调整,
通过deeplink打开第三方app



通过 vite build 后结合 rollup-plugin-visualizer 分析包体积,发现 UI 组件库和图表库占比较大
通过 CDN 外链、按需加载、动态 import 实现代码分割,主包体积从 2.1MB 降到 1.4MB,约下降 30%。

vue3通信大全(三)—— 全局状态管理库pinia,vuex

https://juejin.cn/post/7397285224379957298?searchId=2026022815382985E6324A99D180ACB9B9


state,
actions,
getters

IntersectionObserver

在信息流广告场景中,需要统计广告真实曝光。如果通过 scroll 监听判断元素是否进入视口,会频繁触发计算,性能开销比较大,因此项目中使用了 IntersectionObserver 来实现曝光检测。

具体实现是:当广告组件渲染后,通过 IntersectionObserver 监听广告节点与 viewport 的交叉状态,当元素的 intersectionRatio 超过 50% 时,认为广告进入有效可视区域。为了保证数据准确,我们还增加了曝光停留时间限制,例如停留超过 1 秒才上报曝光埋点。

同时为了避免重复统计,在广告曝光后会取消 observer 监听,并在本地维护曝光缓存,保证同一广告在当前页面只统计一次曝光。点击统计则通过 click 事件进行埋点上报,用于计算广告 CTR 等指标。

在长列表场景下我们还复用了 observer 实例,并在组件销毁时及时取消监听,以避免性能和内存问题

创建 observer

获取需要监听的元素

observer.observe(el)

元素进入视口

触发 callback

根据 dataset 判断执行逻辑
监听完成之后需要取消
observer.unobserve(el)


function observeNewItems() {

  const newItems = document.querySelectorAll('.observe-item')

  newItems.forEach(el => {
    observer.observe(el)
  })

}

// 用于保存每个广告的计时器
// key:adId
// value:setTimeout 的 timer
const visibleAds = new Map()

// 创建 IntersectionObserver
const observer = new IntersectionObserver((entries) => {

  // entries 是所有状态发生变化的元素
  entries.forEach(entry => {

    // 当前被监听的 DOM 元素
    const el = entry.target

    // 从 dataset 中获取广告ID
    const adId = el.dataset.adId

    // 判断广告是否进入可视区域
    // isIntersecting:元素是否进入视口
    // intersectionRatio:可见比例
    if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {

      // 广告进入可视区域,开始1秒计时
      const timer = setTimeout(() => {

        // 如果1秒后广告仍然在 Map 中
        // 说明没有离开可视区域
        if (visibleAds.has(adId)) {

          // 上报广告曝光
          reportExposure(adId)

          // 取消监听,避免重复统计
          observer.unobserve(el)

          // 删除计时器记录
          visibleAds.delete(adId)
        }

      }, 1000)

      // 保存计时器
      visibleAds.set(adId, timer)

    } else {

      // 如果广告离开视口

      // 获取之前的计时器
      const timer = visibleAds.get(adId)

      if (timer) {

        // 清除计时器
        clearTimeout(timer)

        // 删除记录
        visibleAds.delete(adId)

      }

    }

  })

}, {
  // threshold = 0.5 表示至少50%进入视口才触发
  threshold: [0.5]
})

首屏加载慢优化

通过 Chrome Performance + Network 分析

使用 动态 import
CDN 外链,将大体积依赖放 CDN
vite配置 external: ['vue','echarts']
路由懒加载

广告曝光统计不准确

可见面积 ≥ 50%
停留时间 ≥ 1 秒

可见面积 ≥ 50%
停留时间 ≥ 1 秒

进入视口

开始1秒计时

如果离开视口 → 取消

1秒后仍然可见 → 统计曝光
1 收集用户反馈
2 查看监控日志 sentry
3 复现问题
4 Chrome DevTools 排查
5 查看接口请求
6 查看错误日志
7 定位代码

广告封装难度

不同厂商 API 不一致
创建广告方式不同
事件回调不同
加载方式不同

统一广告 SDK 封装

业务层

广告封装层

厂商SDK

广告填充率提高
代码可维护性提升
多个快应用项目可以复用

你对公司有什么想要了解的

目前团队架构是什么样的,主要在开发什么项目
上班时间
我如果有幸入职了,我需要负责什么业务
我想做一个语音识别的网页,输入语音,调用windows电脑的funasr,然后调用大模型接口,回答语音输入的问题,
model_dir = "FunAudioLLM/Fun-ASR-Nano-2512"

model = AutoModel(
    model=model_dir,
    vad_model="fsmn-vad",
    vad_kwargs={"max_single_segment_time": 30000},
    device="cuda:0",
)

看视频学习,

要自信,声音洪亮

低代码平台,

1000w表格渲染,使用canvas花的,然后二进制

截屏2026-03-30 15.39.53

使用github的工作流,上传git之后自动推送到服务器
最近更新