良能前端面经:数组去重、MVVM、v-model 原理与组件通信
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 数组去重怎么实现?
- 谈谈你对 MVVM 的理解,MVVM 有哪些缺点?
v-model的原理是什么?- Vue 组件之间有哪些通信方式?
- 项目:webpack 升级做了什么?
- 项目:做过哪些性能优化?
- 项目:在 AI 方面做过哪些探索?
var、let、const有什么区别?- Vue 中哪些场景需要加
key? for-in和for-of有什么区别?- 常用 git 命令有哪些?
《参考解析》
这轮题单整体是「基础 + 项目」的前端常规面,面试官是部门负责人,所以项目部分比八股更重。 原帖还标注了 18—19k、0—3 个月、五年前端经验,属于要能独立扛业务的层级,回答时最好都带一句「项目里是怎么用的、踩过什么坑」,而不是只背结论。
数组去重按数据类型分场景答,别只甩一个 Set。 简单值最快是 [...new Set(arr)];需要兼容旧环境可以用 filter 配 indexOf。真正的坑在 NaN 和对象上:Set 用 SameValueZero 判定,NaN 能去重,而 indexOf 找不到 NaN;对象数组按引用判重,{a:1} 两条不会被去掉,这时要用 Map 按业务主键(如 id)做桶。再往上一层可以按场景选:需要保留顺序、需要统计重复次数、数据量大时用 Map 计数一次遍历。面试时把这几个边界点补上,比写出代码本身得分更高。
MVVM 的理解要落在「数据驱动视图」和 ViewModel 的职责上。 传统方式是手动拿 DOM 改内容,MVVM 把视图状态抽象成数据模型,ViewModel 负责把 Model 的变化映射成视图更新,视图的交互又反过来写回 Model,开发者只维护数据。它的缺点也要说清:双向绑定让数据流向变得不直观,出问题时排查链路比单向数据流长;绑定本身有内存和计算开销,大列表全量绑定时更明显;视图和模型耦合在框架约定里,复杂交互容易出现难以追踪的隐式更新。Vue 2 用 Object.defineProperty 递归劫持、Vue 3 换 Proxy 支持属性增删与数组索引,这条演进可以顺手带上。
v-model 是语法糖,Vue 2 和 Vue 3 的展开方式不一样。 Vue 2 在表单元素上是 :value 加 @input(checkbox 之类会换成 checked / change),用在自定义组件上默认绑定 value 属性并监听 input 事件,可以在组件里用 model 选项改名。Vue 3 统一成 :modelValue 加 @update:modelValue,好处是可以写多个 v-model:xxx,也能加 .lazy、.number、.trim 修饰符。被追问「为什么 v-model 不能直接绑在 props 上」时,答「props 单向、修改要靠事件,v-model 只是把这两件事写在一起」就到位了。
组件通信按「关系远近」梳理,答成一棵树。 父子用 props 下行、$emit 上行;父子之间还可以用 ref 直接调方法,或者用 v-model 做双向;跨层级用 provide / inject 或 $attrs / $listeners 透传;兄弟或无关系组件用状态管理(Vuex / Pinia)或事件总线(mitt、$bus,Vue 3 里需要自己引入)。再补一句选型原则:能用 props 就别上全局状态,全局状态只放真正跨页面共享的数据,否则可维护性反而下降。顺带说一下 $parent / $children 属于不推荐做法,强耦合且顺序不可控。
key 的场景要从 diff 算法讲。 v-for 需要稳定的 key 让虚拟 DOM 复用正确的节点,用索引作 key 在列表插入、删除、排序时会导致状态错位(比如输入框里的内容跟着序号走);v-if / v-else 同层级切换时给不同 key 可以强制重建组件而不是复用;transition-group 的动画也依赖 key。可以延伸一句:key 变化就等于销毁重建,所以也能用它来主动重置一个组件的内部状态。
var / let / const 与 for-in / for-of 两题都是基础,但都有常见追问。 var 是函数作用域、有变量提升、可重复声明;let / const 是块级作用域,存在暂时性死区,不可重复声明;const 锁的是绑定而不是值,对象内部仍可改。for-in 遍历的是可枚举属性名(含原型链上的,通常要配 hasOwnProperty),适合对象;for-of 走迭代器协议,适合数组、字符串、Map、Set 和类数组,可以 break / return,但不支持普通对象(除非自己实现 Symbol.iterator)。for-of 遍历对象要配 Object.entries 或 Object.keys,这条经常被接着问。
项目三问是这轮的重点,答法要带数字和取舍。 webpack 升级(比如 4 升 5)主线是构建提效:升级后开启持久化缓存、用 splitChunks 拆包、修正被废弃的配置(hash 全部换 fullhash / contenthash)、清理失效插件,同时说清迁移中遇到的不兼容点和怎么回滚。性能优化分构建侧和运行侧答:构建侧有 tree-shaking、缩小 loader 的 include 范围、按需引入、产物分析;运行侧有路由懒加载、图片压缩与 CDN、长列表虚拟滚动、防抖节流、骨架屏,并给出指标(首屏时间、构建耗时、包体积)的前后对比。AI 探索部分讲清用了什么、解决了什么实际问题,比如用 AI 辅助生成单测与类型声明、做代码评审检查、或接入 AI 能力到业务里,重点是产出和边界,而不是工具名单。
git 命令别只背 add / commit / push。 日常流程讲一遍之后,主动补三类救场命令会加分:改错了用 reset(未推送)或 revert(已推送,保留历史)回退,误删找回用 reflog,临时切换用 stash;协作里 rebase 与 merge 的区别、cherry-pick 挑单个提交、fetch 与 pull 的差别、冲突解决流程也常被追问。能说清「什么时候不该 rebase 公共分支」是这条题的加分项。