前言
大家好,我是木斯佳。
在这个春节假期,当大家都在谈论返乡、团圆与休息时,作为一名技术人,我的思考却不由自主地转向了行业的「冬」与「春」。
相信很多人都感受到了,在AI浪潮的席卷之下,前端领域的门槛在变高,纯粹的"增删改查"岗位正在肉眼可见地减少。曾经热闹非凡的面经分享,如今也沉寂了许多。但我们都知道,市场的潮水退去,留下的才是真正在踏实准备、努力沉淀的人。学习的需求,从未消失,只是变得更加务实和深入。
正值春节,也是复盘与规划的好时机。结合CSDN这次「春节代码贺新年」活动所提倡的"用技术视角记录春节、复盘成长",我决定在这个假期持续更新专栏,帮助年后参加春招的同学。
这个专栏的初衷很简单:拒绝过时的、流水线式的PDF引流贴,专注于收集和整理当下最新、最真实的前端面试资料。我会在每一份面经和八股文的基础上,尝试从面试官的角度去拆解问题背后的逻辑,而不仅仅是提供一份静态的背诵答案。无论你是校招还是社招,目标是中大厂还是新兴团队,只要是真实发生、有价值的面试经历,我都会在这个专栏里为你沉淀下来。
温馨提示:市面上的面经鱼龙混杂,甄别真伪、把握时效,是我们对抗内卷最有效的武器。
在这个假期,让我们一起充电,为下一个技术春天做好准备。

面经原文内容
📍面试公司:万兴科技
🕐面试时间:近期,用户2月3号上传
💻面试岗位:前端实习
💬面试风格:底层原理型 + 工程化深挖 + AI结合
📝候选人感受:被狠狠拷打,问的都是不会的,背了但忘记底层,没几个答上来
❓面试问题:
八股(底层向)
- Vue2和Vue3的虚拟DOM的区别
- Vue2和Vue3的patch
- WebWorker
- Wasm有没有了解过
- Webpack-plugin
- React Native有用过吗
- 框架的源码有没有看过(脑子抽了说没有)
- 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场景
- 期望有源码阅读能力:至少看过核心部分
突击复习建议
- Vue3源码:看响应式、编译优化部分
- 手写代码:Promise、Plugin、WebWorker demo
- 前沿技术:Wasm入门、WebWorker实战
- 项目优化:准备2-3个优化案例,带上数据
- 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辅助编程 |
📌 最后一句:
被"狠狠拷打"不可怕,可怕的是不知道自己缺什么。
这次面试就像一面镜子,照出了你的知识盲区,希望可以好好复习,下次再战