前言
大家好,我是木斯佳。
相信很多人都感受到了,在AI浪潮的席卷之下,前端领域的门槛在变高,纯粹的“增删改查”岗位正在肉眼可见地减少。曾经热闹非凡的面经分享,如今也沉寂了许多。但我们都知道,市场的潮水退去,留下的才是真正在踏实准备、努力沉淀的人。学习的需求,从未消失,只是变得更加务实和深入。
这个专栏的初衷很简单:拒绝过时的、流水线式的PDF引流贴,专注于收集和整理当下最新、最真实的前端面试资料。我会在每一份面经和八股文的基础上,尝试从面试官的角度去拆解问题背后的逻辑,而不仅仅是提供一份静态的背诵答案。无论你是校招还是社招,目标是中大厂还是新兴团队,只要是真实发生、有价值的面试经历,我都会在这个专栏里为你沉淀下来。专栏快速链接
温馨提示:市面上的面经鱼龙混杂,甄别真伪、把握时效,是我们对抗内卷最有效的武器。
面经原文内容
📍面试公司:美团财务科技
🕐面试时间:4月9日上午11点,时长25分钟
💻面试岗位:前端日常一面
📝面试体验:人生第一次面试,面试官很友善,基本都是简单八股
❓面试问题:
- JS 的数据类型有几种
- 基础数据类型和引用数据类型的本质区别
- js 定义变量的方式有几种
- let 和 var 有什么区别
- promise 解决什么问题
- 箭头函数跟普通函数有什么区别
- ES6 向 ES5 的转换一般是怎么做的
- 用 webpack 多一些还是 Vite 多一些
- Vite 有哪些配置项你常用的
- Vue 父子组件传递参数该怎么传
- vue 3 里面做全局状态管理该一般是怎么做
- 学生管理系统从 0 到 1 技术选型,框架用 Vue 还是 react,打包工具用哪一个,UI 组件库用哪一个,说明理由
- 手撕:143. 重排链表
来源:牛客网 前端死了咩
💡木木有话说(刷前先看)
美团这场日常实习一面,是一份非常标准的基础面经。面试官友善,题目基础,没有深挖项目,可能是因为技术栈差异或日常实习门槛较低。问题覆盖JS基础、ES6、构建工具、Vue核心、技术选型,最后一道手撕链表题。对于第一次面试的同学来说,这份面经很有参考价值——基础扎实,就能从容应对。
📝 美团财务科技前端一面·深度解析
🎯面试整体画像
| 维度 | 特征 |
|---|---|
| 面试风格 | 基础友好型 + 标准八股 + 无压力追问 |
| 难度评级 | ⭐⭐(二星,基础为主,适合新手) |
| 考察重心 | JS数据类型、ES6特性、构建工具、Vue核心、技术选型 |
| 特殊之处 | 日常实习门槛较低,偏重基础而非项目深度 |
🔍逐题深度解析
二、JS的数据类型有几种
回答思路:最新ECMAScript标准有8种数据类型。
分类:
- 基础数据类型(7种):
number、string、boolean、null、undefined、symbol(ES6)、bigint(ES2020) - 引用数据类型(1种):
object(包含数组、函数、日期、正则等)
typeof123// 'number'typeof'str'// 'string'typeoftrue// 'boolean'typeofundefined// 'undefined'typeofnull// 'object'(历史遗留bug)typeofSymbol()// 'symbol'typeof123n// 'bigint'typeof{}// 'object'typeof[]// 'object'typeoffunction(){}// 'function'三、基础数据类型和引用数据类型的本质区别
回答思路:从存储位置、赋值方式、比较方式三个维度说明。
| 维度 | 基础数据类型 | 引用数据类型 |
|---|---|---|
| 存储位置 | 栈内存(固定大小) | 堆内存(动态大小),栈存引用地址 |
| 赋值方式 | 值拷贝(独立副本) | 引用拷贝(指向同一对象) |
| 比较方式 | 值比较 | 引用地址比较 |
// 基础类型:值拷贝leta=10letb=a b=20console.log(a)// 10(不变)// 引用类型:引用拷贝letobj1={name:'Tom'}letobj2=obj1 obj2.name='Jerry'console.log(obj1.name)// 'Jerry'(被修改)// 比较10===10// true{name:'Tom'}==={name:'Tom'}// false(不同对象)四、js定义变量的方式有几种
回答思路:ES6之前有var,ES6新增let和const。
| 方式 | 作用域 | 变量提升 | 重复声明 | 可修改 |
|---|---|---|---|---|
var | 函数作用域 | 是(undefined) | 允许 | 是 |
let | 块级作用域 | 否(TDZ) | 不允许 | 是 |
const | 块级作用域 | 否(TDZ) | 不允许 | 否(属性可改) |
vara=1letb=2constc=3// const声明的对象属性可以修改constobj={name:'Tom'}obj.name='Jerry'// 允许五、let和var有什么区别
回答思路:从作用域、变量提升、重复声明、全局属性四个角度回答。
区别:
- 作用域:
var函数作用域,let块级作用域({}内) - 变量提升:
var提升但值为undefined,let提升但存在暂时性死区(TDZ) - 重复声明:
var允许重复声明,let不允许 - 全局声明:
var在全局声明会成为window属性,let不会
// 块级作用域{vara=1letb=2}console.log(a)// 1console.log(b)// ReferenceError// 暂时性死区console.log(x)// undefined(var提升)varx=1console.log(y)// ReferenceError(TDZ)lety=2六、promise解决什么问题
回答思路:Promise是异步编程的解决方案。
解决的问题:
- 回调地狱:避免多层嵌套的回调函数
- 错误处理:统一的
.catch()捕获异步错误 - 并发控制:
Promise.all、Promise.race等处理多个异步操作
// 回调地狱getData(function(a){getMoreData(a,function(b){getMoreData(b,function(c){console.log(c)})})})// Promise链式调用getData().then(a=>getMoreData(a)).then(b=>getMoreData(b)).then(c=>console.log(c)).catch(err=>console.error(err))七、箭头函数跟普通函数的区别
回答思路:从this绑定、arguments、构造函数、prototype等角度回答。
| 特性 | 普通函数 | 箭头函数 |
|---|---|---|
this | 动态绑定(调用时决定) | 静态绑定(定义时继承外层) |
arguments | 有 | 无(可用rest参数替代) |
| 构造函数 | 可以(new调用) | 不可以(会报错) |
prototype | 有 | 无 |
| 简写 | 无 | 单参数可省略括号,单语句可省略return |
// this指向constobj={name:'Tom',normalFn:function(){console.log(this.name)// Tom(调用时指向obj)},arrowFn:()=>{console.log(this.name)// undefined(继承外层,通常是window)}}// 不能作为构造函数constFn=()=>{}constf=newFn()// TypeError八、ES6向ES5的转换一般是怎么做的
回答思路:使用Babel进行转译。
流程:
- 解析(Parse):将ES6代码解析成AST(抽象语法树)
- 转换(Transform):将ES6语法对应的AST节点转换为ES5节点
- 生成(Generate):将转换后的AST生成ES5代码
核心插件:@babel/preset-env,根据目标浏览器环境自动决定转换哪些特性。
// 配置示例(.babelrc){"presets":[["@babel/preset-env",{"targets":"> 0.25%, not dead"}]]}常见转换:
const/let→var- 箭头函数 → 普通函数
- 模板字符串 → 字符串拼接
class→ 构造函数 + 原型方法
九、用webpack多一些还是Vite多一些
回答思路:根据项目类型选择。
回答示例:
“我平时用Vite多一些,因为它开发环境启动快、热更新快。但在一些需要精细控制打包配置的老项目或复杂项目中,也会用到Webpack。”
十、Vite有哪些配置项你常用的
回答思路:列举常用配置。
// vite.config.jsexportdefault{// 插件plugins:[vue(),react()],// 路径别名resolve:{alias:{'@':'/src'}},// 开发服务器server:{port:3000,proxy:{'/api':'http://localhost:8080'}},// 构建配置build:{outDir:'dist',sourcemap:true,rollupOptions:{external:['react']}},// CSS预处理器css:{preprocessorOptions:{scss:{additionalData:`@import "@/styles/variables.scss";`}}}}十一、Vue父子组件传递参数
回答思路:父传子用props,子传父用emit。
父传子:
<!-- 父组件 --> <template> <Child :message="parentMsg" /> </template> <script setup> import Child from './Child.vue' const parentMsg = 'Hello from parent' </script> <!-- 子组件 --> <script setup> const props = defineProps(['message']) console.log(props.message) </script>子传父:
<!-- 子组件 --> <script setup> const emit = defineEmits(['update']) emit('update', 'data from child') </script> <!-- 父组件 --> <template> <Child @update="handleUpdate" /> </template> <script setup> const handleUpdate = (data) => { console.log(data) } </script>十二、Vue3全局状态管理
回答思路:Vue3推荐使用Pinia(官方状态管理库)。
Pinia特点:
- 轻量、TypeScript友好
- 去掉了mutations(只有state、getters、actions)
- 支持Vue DevTools
// stores/user.jsimport{defineStore}from'pinia'exportconstuseUserStore=defineStore('user',{state:()=>({name:'Tom',age:18}),getters:{doubleAge:(state)=>state.age*2},actions:{updateName(newName){this.name=newName}}})// 组件中使用import{useUserStore}from'@/stores/user'constuserStore=useUserStore()console.log(userStore.name)userStore.updateName('Jerry')十三、学生管理系统技术选型
回答思路:说明选型理由,展现思考过程。
框架:选择Vue(因为熟悉,上手快;React也很优秀,但团队倾向Vue)
打包工具:选择Vite(开发环境启动快,热更新体验好,适合中小型项目)
UI组件库:
- Element Plus:Vue3生态最成熟的桌面端组件库,适合后台管理系统
- Ant Design Vue:设计规范统一,但体积略大
- Naive UI:TypeScript友好,但生态较新
推荐:Element Plus + Vite + Vue3 + Pinia
二十、手撕:143. 重排链表
题目:将链表L0 → L1 → ... → Ln-1 → Ln重排为L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → ...
解题思路:
- 找到链表中点(快慢指针)
- 反转后半部分链表
- 交替合并两个链表
functionreorderList(head){if(!head||!head.next)return// 1. 找中点letslow=head,fast=headwhile(fast.next&&fast.next.next){slow=slow.next fast=fast.next.next}// 2. 反转后半部分letprev=nullletcurr=slow.next slow.next=null// 断开前后while(curr){constnext=curr.next curr.next=prev prev=curr curr=next}// 3. 交替合并letfirst=headletsecond=prevwhile(second){constnext1=first.nextconstnext2=second.next first.next=second second.next=next1 first=next1 second=next2}}时间复杂度:O(n)
空间复杂度:O(1)
📚知识点速查表
| 知识点 | 核心要点 |
|---|---|
| JS数据类型 | 7种基础(number/string/boolean/null/undefined/symbol/bigint)+ object |
| 基础vs引用 | 栈存值/堆存址、值拷贝/引用拷贝、值比较/地址比较 |
| 定义变量 | var(函数作用域)、let/const(块级作用域)、const不可重新赋值 |
| let vs var | 块级作用域、TDZ、不能重复声明、不挂载window |
| Promise | 解决回调地狱、统一错误处理、并发控制 |
| 箭头函数 | this静态绑定、无arguments、不能new、无prototype |
| ES6转ES5 | Babel解析→转换→生成,@babel/preset-env |
| Vite配置 | plugins、resolve.alias、server.proxy、build |
| Vue父子通信 | props(父→子)、emit(子→父) |
| 全局状态 | Pinia(state/getters/actions) |
| 技术选型 | Vue3 + Vite + Element Plus + Pinia |
| 重排链表 | 找中点→反转后半→交替合并 |
📌 最后一句:
美团这场日常一面,是一份“新手友好”的基础面经。题目虽简单,但覆盖了JS核心、ES6、构建工具、Vue基础等必备知识。对于第一次面试的同学来说,这样的面试有助于建立信心——只要基础扎实,就能从容应对。从用户反馈看,面试完当天下午就约了二面,说明表现不错。基础是前端的立身之本,把地基打牢,才能走得更远。