前端八股文面经大全:万兴科技前端实习一面(2026-2-3)·面经深度解析

前言

大家好,我是木斯佳。

在这个春节假期,当大家都在谈论返乡、团圆与休息时,作为一名技术人,我的思考却不由自主地转向了行业的「冬」与「春」。

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

正值春节,也是复盘与规划的好时机。结合CSDN这次「春节代码贺新年」活动所提倡的"用技术视角记录春节、复盘成长",我决定在这个假期持续更新专栏,帮助年后参加春招的同学。

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

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

在这个假期,让我们一起充电,为下一个技术春天做好准备。

面经原文内容

📍面试公司:万兴科技

🕐面试时间:近期,用户2月3号上传

💻面试岗位:前端实习

💬面试风格:底层原理型 + 工程化深挖 + AI结合

📝候选人感受:被狠狠拷打,问的都是不会的,背了但忘记底层,没几个答上来

❓面试问题:

八股(底层向)

  1. Vue2和Vue3的虚拟DOM的区别
  2. Vue2和Vue3的patch
  3. WebWorker
  4. Wasm有没有了解过
  5. Webpack-plugin
  6. React Native有用过吗
  7. 框架的源码有没有看过(脑子抽了说没有)
  8. Promise异步加载(三种状态),有没有手写过

项目拷打

  • 优化是怎么做的
  • 你们公司怎么处理的
  • 你们公司用什么AI编辑器

来源:牛客网 咪咪虫

📝 万兴科技前端实习一面·面经深度解析

🎯 面试整体画像

维度 特征
公司定位 万兴科技 - AIGC软件上市公司(Wondershare)
面试风格 底层原理型 + 工程化深挖 + AI场景结合
难度评级 ⭐⭐⭐⭐(四星,实习面考察偏底层八股)
考察重心 虚拟DOM diff、构建工具、多线程、跨端技术
特殊之处 AI编辑器问题(结合公司业务方向)

🔍 逐题深度解析

一、Vue2 vs Vue3 虚拟DOM区别

问题:Vue2和Vue3的虚拟DOM的区别
javascript 复制代码
// 1. 数据结构差异

// Vue2 VNode结构(简化)
{
  tag: 'div',
  data: { class: 'container' },
  children: [...],
  text: undefined,
  elm: DOM节点,
  key: 'key'
}

// Vue3 VNode结构(更扁平,性能更好)
{
  type: 'div',        // 类型
  props: { class: 'container' },  // 属性
  children: [...],     // 子节点
  shapeFlag: 9,        // 形状标记(位运算优化)
  patchFlag: 1,        // 补丁标记(动态节点标记)
  dynamicProps: [...]  // 动态属性列表
}
2. 编译时优化差异
javascript 复制代码
// Vue2:全量diff
// 组件更新时,会递归遍历所有子节点进行比较

// Vue3:静态提升 + 补丁标记
// 模板编译阶段:

// 原始模板
<div>
  <div>静态文字</div>
  <div :class="dynamic">动态内容</div>
</div>

// 编译结果(简化)
// 静态节点提升(只创建一次)
const _hoisted_1 = _createVNode("div", null, "静态文字", -1 /* HOISTED */)

// 动态节点带补丁标记
_createVNode("div", { class: dynamic }, null, 1 /* CLASS */)

// diff时只对比带patchFlag的节点
3. 核心区别总结
维度 Vue2 Vue3
diff策略 全量比较 靶向更新(只比较动态部分)
静态节点 每次重新创建 静态提升(只创建一次)
标记方式 无标记 patchFlag标记动态类型
性能 模板越大越慢 与模板大小无关,只与动态节点数相关
缓存 事件缓存(避免重复创建函数)

二、Vue2 vs Vue3 patch

问题:Vue2和Vue3的patch
javascript 复制代码
// patch = 补丁/打补丁 = diff算法的执行过程

// Vue2 patch流程(简化)
function patchVnode(oldVnode, vnode) {
  const el = vnode.el = oldVnode.el
  
  // 1. 如果props变化,更新属性
  updateProperties(vnode)
  
  // 2. 处理子节点
  if (vnode.text && oldVnode.text !== vnode.text) {
    // 文本节点更新
    setTextContent(el, vnode.text)
  } else {
    // 对比子节点
    updateChildren(el, oldVnode.children, vnode.children)
  }
}

// Vue3 patch流程(优化版)
function patch(n1, n2, container) {
  // 1. 快速检查patchFlag
  if (n2.patchFlag > 0) {
    if (n2.patchFlag & 1 /* CLASS */) {
      // 只更新class
      patchClass(n2)
    }
    if (n2.patchFlag & 2 /* STYLE */) {
      // 只更新style
      patchStyle(n2)
    }
    // 不需要遍历所有属性
  } else {
    // 没有标记才全量对比
    fullPatchProps(n1, n2)
  }
  
  // 2. 子节点对比(优化版)
  if (n2.dynamicChildren) {
    // 只对比动态子节点
    patchBlockChildren(n1.dynamicChildren, n2.dynamicChildren)
  } else {
    // 全量对比
    patchChildren(n1, n2)
  }
}
关键优化点
  • patchFlag:标记节点哪些部分是动态的(class/style/text/children)
  • Block Tree:收集动态子节点,跳过静态节点
  • 快速路径:针对不同类型更新使用专用函数

三、WebWorker

问题:WebWorker是什么?怎么用?
javascript 复制代码
// WebWorker:浏览器后台线程,用于执行耗时任务,不阻塞UI

// 主线程 main.js
const worker = new Worker('worker.js')

// 发送消息给worker
worker.postMessage({ type: 'compute', data: largeArray })

// 接收worker返回结果
worker.onmessage = (e) => {
  console.log('计算结果:', e.data)
  updateUI(e.data)
}

worker.onerror = (error) => {
  console.error('worker错误:', error)
}

// worker线程 worker.js
self.onmessage = (e) => {
  const { type, data } = e.data
  
  if (type === 'compute') {
    // 执行耗时计算(不阻塞主线程)
    const result = heavyComputation(data)
    
    // 返回结果
    self.postMessage(result)
  }
}

// 终止worker
worker.terminate()
应用场景
javascript 复制代码
// 1. 大量数据处理
- 图像/视频处理(如万兴的视频编辑)
- 大数据排序/过滤
- 加密解密

// 2. 复杂计算
- 3D渲染计算
- 编译器/转译器
- 代码格式化

// 3. 实时数据处理
- 音频分析
- 实时通信数据处理
注意事项
  • Worker不能访问DOM
  • 跨域限制(需同源)
  • 通信是拷贝传递(大对象有性能开销)
  • 可考虑Transferable Objects优化(转移而非拷贝)

四、Wasm(WebAssembly)

问题:Wasm有没有了解过?
javascript 复制代码
// WebAssembly:二进制指令格式,接近原生性能

// 为什么需要Wasm?
// 1. 性能接近原生(C++/Rust编译而来)
// 2. 支持语言多(C/C++/Rust/Go等)
// 3. 安全(沙盒环境)

// 使用场景(万兴特别相关)
// 1. 视频/图像编解码(Filmora视频编辑)
// 2. 3D渲染引擎
// 3. 游戏引擎
// 4. 加密算法
// 5. 语音/图像识别

// 基本使用
// 加载wasm模块
WebAssembly.instantiateStreaming(fetch('module.wasm'), {
  env: {
    consoleLog: (ptr, len) => {
      // 从内存读取字符串
      const str = memoryToString(ptr, len)
      console.log(str)
    }
  }
}).then(result => {
  const { instance } = result
  // 调用wasm导出的函数
  const result = instance.exports.compute(data)
})

// 和WebWorker结合
// Worker处理复杂计算 + Wasm提供高性能计算能力
前端为什么关注Wasm?
  • 处理JS性能瓶颈
  • 复用已有C++库(万兴有很多底层视频处理库)
  • 视频编辑、PDF处理等重计算场景

五、Webpack Plugin

问题:Webpack-plugin原理和实现
javascript 复制代码
// Webpack插件:在webpack构建流程中注入自定义逻辑

// 插件基本结构
class MyPlugin {
  constructor(options) {
    this.options = options
  }
  
  // 必须实现apply方法
  apply(compiler) {
    // compiler:webpack编译器实例
    
    // 监听钩子
    compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
      // compilation:当前构建的上下文
      
      // 遍历所有资源文件
      const assets = compilation.assets
      
      Object.keys(assets).forEach(filename => {
        // 修改文件内容
        let content = assets[filename].source()
        content = content.replace(/__VERSION__/g, this.options.version)
        
        // 更新资源
        compilation.assets[filename] = {
          source: () => content,
          size: () => content.length
        }
      })
      
      callback()
    })
    
    // 其他常用钩子
    compiler.hooks.compile.tap('MyPlugin', () => {
      console.log('编译开始')
    })
    
    compiler.hooks.done.tap('MyPlugin', (stats) => {
      console.log('编译完成')
    })
  }
}

// 使用插件
module.exports = {
  plugins: [
    new MyPlugin({ version: '1.0.0' })
  ]
}
常见插件原理
javascript 复制代码
// 1. HtmlWebpackPlugin:生成HTML文件
- 在emit阶段生成HTML
- 自动注入bundle

// 2. MiniCssExtractPlugin:提取CSS
- 监听renderManifest钩子
- 将CSS从JS中分离

// 3. DefinePlugin:定义全局常量
- 在编译时替换代码中的变量

// 4. 自己写过的插件(如果有)
- 版本注入插件
- 日志统计插件

六、框架源码

问题:框架的源码有没有看过?

候选人反思:脑子抽了说没有,应该扯点双向绑定和vite热更新打包啥的

✅ 正确回答思路
javascript 复制代码
// 如果没有完整读过,可以这样说:
"我没有完整读过Vue/React的全部源码,但我对核心原理有深入研究:

1. Vue响应式原理
   - Vue2使用Object.defineProperty
   - Vue3使用Proxy
   - 自己实现过简单的响应式系统

2. 虚拟DOM diff
   - 了解同层比较、key的作用
   - Vue3的patchFlag优化

3. Vite热更新
   - 基于ES Module
   - 利用浏览器原生import

4. 最近在看的部分
   - 最近正在看Vue3的编译优化部分
   - 对xxx特别感兴趣

这样既诚实(没说完整读过),又展示了学习深度和兴趣。

七、Promise异步加载

问题:Promise三种状态,有没有手写过?
javascript 复制代码
// Promise三种状态
// pending(进行中)→ fulfilled(已成功)或 rejected(已失败)

// 手写Promise(简化版)
class MyPromise {
  constructor(executor) {
    this.state = 'pending'  // pending/fulfilled/rejected
    this.value = undefined
    this.reason = undefined
    this.onFulfilledCallbacks = []
    this.onRejectedCallbacks = []
    
    const resolve = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled'
        this.value = value
        this.onFulfilledCallbacks.forEach(fn => fn())
      }
    }
    
    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.reason = reason
        this.onRejectedCallbacks.forEach(fn => fn())
      }
    }
    
    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }
  
  then(onFulfilled, onRejected) {
    if (this.state === 'fulfilled') {
      onFulfilled(this.value)
    }
    if (this.state === 'rejected') {
      onRejected(this.reason)
    }
    if (this.state === 'pending') {
      this.onFulfilledCallbacks.push(() => onFulfilled(this.value))
      this.onRejectedCallbacks.push(() => onRejected(this.reason))
    }
  }
}

// 手写Promise.all
MyPromise.all = function(promises) {
  return new MyPromise((resolve, reject) => {
    const results = []
    let completed = 0
    
    promises.forEach((promise, index) => {
      MyPromise.resolve(promise).then(value => {
        results[index] = value
        completed++
        if (completed === promises.length) {
          resolve(results)
        }
      }).catch(reject)
    })
  })
}

🎯 项目拷打部分

问题:优化是怎么做的?

javascript 复制代码
// 回答框架:问题→方案→效果

// 1. 首屏加载优化
// 问题:首屏JS过大,白屏时间长
// 方案:
- 路由懒加载
- 图片懒加载
- 关键CSS内联
// 效果:FCP从2.3s降到1.2s

// 2. 运行时性能优化
// 问题:列表渲染卡顿
// 方案:
- 虚拟滚动(react-window/vue-virtual-scroller)
- 使用key优化diff
- 避免不必要的重渲染(memo/useMemo)
// 效果:滚动帧率从30fps提升到60fps

// 3. 资源优化
// 问题:打包体积过大
// 方案:
- Tree Shaking
- 代码分割
- 图片压缩/WebP
// 效果:打包体积从5MB降到2.3MB

// 4. 网络优化
// 问题:接口请求慢
// 方案:
- 缓存策略
- 并发请求
- 数据预取
// 效果:数据加载时间减少40%

🧠 面试复盘与备考建议

为什么被"狠狠拷打"?

问题类型 暴露的问题 改进方向
Vue2/3 diff 只背了概念,没理解源码 看源码注释,自己画流程图
WebWorker 知道概念没用过 写个小demo(图片处理/计算)
Wasm 没关注过前沿技术 关注技术趋势,看入门教程
Webpack Plugin 只会用不会写 写个简单插件试试
框架源码 没看过 从核心原理开始,不要贪多
项目优化 没量化效果 准备数据说话

万兴科技面试特点

  • 重视底层原理:不是会用框架就行,要懂原理
  • 关注前沿技术:Wasm、WebWorker、AI工具
  • 业务结合紧密:视频编辑、AIGC场景
  • 期望有源码阅读能力:至少看过核心部分

突击复习建议

  1. Vue3源码:看响应式、编译优化部分
  2. 手写代码:Promise、Plugin、WebWorker demo
  3. 前沿技术:Wasm入门、WebWorker实战
  4. 项目优化:准备2-3个优化案例,带上数据
  5. AI工具:了解Cursor/Copilot,有自己的使用心得

📚 知识点速查表

知识点 核心要点
Vue2/3虚拟DOM patchFlag、静态提升、靶向更新
patch流程 全量vs标记、Block Tree、快速路径
WebWorker 后台线程、postMessage、适用场景
Wasm 二进制指令、高性能计算、视频编辑
Webpack Plugin 生命周期钩子、compiler/compilation
React Native 跨端、桥接、原生组件
框架源码 响应式、diff、编译优化
Promise 三种状态、手写实现
性能优化 首屏、运行时、资源、网络
AI编辑器 Cursor/Copilot、AI辅助编程

📌 最后一句:

被"狠狠拷打"不可怕,可怕的是不知道自己缺什么。

这次面试就像一面镜子,照出了你的知识盲区,希望可以好好复习,下次再战

相关推荐
yuki_uix2 小时前
别让 AI 骗了:这些状态管理工具真的适合你吗?
前端·ai编程
日月云棠2 小时前
UE5 打包后 EXE 程序单实例的两种实现方法
前端·c++
滕青山2 小时前
Base64编码/解码 核心JS实现
前端·javascript·vue.js
Novlan12 小时前
@tdesign/uniapp 常见问题
前端
sww_10262 小时前
SAA ReactAgent工作原理
开发语言·前端·javascript
linux_cfan2 小时前
拒绝“黑屏”与“哑剧”:Web视频播放器UX体验与自动播放选型指南 (2026版)
前端·javascript·音视频·html5·ux
小庄梦蝶2 小时前
宝塔使用nodejs管理器下载nodejs版本失败解决方式之一
linux·运维·前端
be or not to be2 小时前
假期js学习汇总
前端·javascript·学习
SuperEugene2 小时前
日期与时间处理:不用库和用 dayjs 的两种思路
前端·javascript