前言大家好我是木斯佳。相信很多人都感受到了在AI浪潮的席卷之下前端领域的门槛在变高纯粹的“增删改查”岗位正在肉眼可见地减少。曾经热闹非凡的面经分享如今也沉寂了许多。但我们都知道市场的潮水退去留下的才是真正在踏实准备、努力沉淀的人。学习的需求从未消失只是变得更加务实和深入。这个专栏的初衷很简单拒绝过时的、流水线式的PDF引流贴专注于收集和整理当下最新、最真实的前端面试资料。我会在每一份面经和八股文的基础上尝试从面试官的角度去拆解问题背后的逻辑而不仅仅是提供一份静态的背诵答案。无论你是校招还是社招目标是中大厂还是新兴团队只要是真实发生、有价值的面试经历我都会在这个专栏里为你沉淀下来。专栏快速地址温馨提示市面上的面经鱼龙混杂甄别真伪、把握时效是我们对抗内卷最有效的武器。面经原文内容面试公司正泰电气面试时间近期面试岗位前端实习一面❓面试问题一、八股相关常用 HTML5 标签标签语义化SEO优化怎么做TypeScript防御性编程会怎么去做interface 与 type 的区别如何获取函数入参类型二次封装ParametersT事件委托原理React 组件内 onClick 与 document.addEventListener 谁先触发useEffect 与 useLayoutEffect 区别React 任务调度与优先级二、项目相关瀑布流布局如何实现长列表渲染优化方案大图 / 大量计算如何避免阻塞主线程Web Worker、WebAssemblyZustand 与 Redux 区别三、场景题全局异常捕获与上报设计思路框架解耦的通用 SDK 设计来源牛客网eGgo3木木有话说刷前先看工程化思维是AI时代前端必须掌握的一个能力。很多面试官习惯从项目中问或者架空场景问也是考量候选人综合解决问题的能力这篇面经适合已经有一定项目经验、准备冲击中大厂实习的同学。 正泰电气前端实习一面·深度解析面试整体画像维度特征面试风格基础进阶混合型 工程实战型 场景设计型难度评级⭐⭐⭐⭐四星TS高级类型、React调度、异常捕获SDK较深考察重心HTML语义化/SEO、TS类型编程、React事件机制、性能优化、错误监控特殊之处场景题“全局异常捕获SDK”非常实战考察工程化设计能力逐题深度解析一、常用 HTML5 标签回答思路列举新增的语义化标签和功能标签。语义化标签header、nav、main、article、section、aside、footer多媒体标签video、audio、canvas、svg表单增强input typeemail/number/date/range、datalist、progress、meter其他details/summary折叠面板、dialog对话框二、标签语义化定义使用具有明确含义的HTML标签而非通用div/span。作用SEO搜索引擎更准确识别内容结构提升排名可访问性屏幕阅读器能更好地理解页面辅助残障人士可维护性代码结构清晰团队协作效率高浏览器兼容部分标签有默认样式和行为三、SEO优化怎么做回答思路从标签、内容、性能、技术四个维度说明。标签层面设置title关键词前置、meta namedescription吸引点击使用语义化标签h1~h6层级清晰图片加alt属性链接加relnofollow外部链接内容层面关键词密度合理2%-8%内链策略相关页面互相链接内容原创、定期更新性能层面首屏加载速度LCP 2.5s移动端适配响应式设计技术层面服务端渲染SSR或预渲染生成sitemap.xml和robots.txt使用结构化数据JSON-LD!-- 结构化数据示例 --scripttypeapplication/ldjson{context:https://schema.org,type:Article,headline:文章标题,description:文章描述}/script四、TypeScript防御性编程回答思路防御性编程是“假设最坏情况提前防范错误”。TypeScript中的实践严格模式strict: true启用所有严格类型检查使用unknown替代any强制类型守卫后才使用可选链?.和空值合并??安全访问嵌套属性类型守卫is关键字、instanceof、typeof联合类型和穷尽性检查never类型确保所有分支处理// 防御性函数设计functionprocessInput(input:unknown):string{// 类型守卫if(typeofinput!string){thrownewError(输入必须是字符串)}if(input.length0){return默认值}returninput.trim()}// 穷尽性检查typeStatuspending|success|errorfunctionhandleStatus(status:Status){switch(status){casepending:return加载中casesuccess:return成功caseerror:return失败default:{const_exhaustiveCheck:neverstatusthrownewError(未处理的状态:${_exhaustiveCheck})}}}五、interface 与 type 的区别维度interfacetype声明合并✅ 可以同名自动合并❌ 不可以会报错扩展方式extends交叉类型实现类✅ 可以用implements❌ 不支持声明类型对象、函数、类所有类型联合、元组、原始类型计算属性❌ 不支持✅ 支持type Keys a | b// 声明合并interfaceUser{name:string}interfaceUser{age:number}// 合并为 { name: string; age: number }// type适用场景typeIDstring|number// 联合类型typePoint[number,number]// 元组typeKeysname|age// 字面量联合建议优先使用interface可扩展、性能好需要联合类型或元组时用type。六、如何获取函数入参类型ParametersT回答思路ParametersT是TypeScript内置的工具类型用于提取函数类型的参数类型。// 定义typeParametersTextends(...args:any)anyTextends(...args:inferP)any?P:never// 使用示例functiongreet(name:string,age:number):void{console.log(${name},${age})}typeGreetParamsParameterstypeofgreet// [string, number]// 二次封装场景包装函数保持参数类型一致functionwrapFunctionTextends(...args:any[])any(fn:T){returnfunction(...args:ParametersT):ReturnTypeT{console.log(调用前,args)constresultfn(...args)console.log(调用后,result)returnresult}}constwrappedGreetwrapFunction(greet)wrappedGreet(Tom,18)// 类型安全七、事件委托原理定义利用事件冒泡机制将子元素的事件监听委托给父元素统一处理。原理事件触发后从目标元素向上冒泡到父元素父元素监听器通过event.target判断实际触发元素根据target匹配选择器执行对应回调优点减少内存占用少绑定监听器动态添加的子元素无需重新绑定// 事件委托示例document.getElementById(list).addEventListener(click,(e){if(e.target.matches(li.item)){console.log(点击了,e.target.textContent)}})八、React组件内onClick与document.addEventListener谁先触发答案document.addEventListener先触发在冒泡阶段。原因React的合成事件是在documentReact 16或root节点React 17上通过事件委托实现的原生事件document.addEventListener在React合成事件之前执行冒泡阶段执行顺序原生捕获 → 目标阶段 → 原生冒泡 → React合成事件冒泡// 验证示例document.addEventListener(click,()console.log(原生事件))functionApp(){returnbutton onClick{()console.log(React合成事件)}点击/button}// 点击输出原生事件 → React合成事件注意React 17事件委托到root节点但原生事件仍然先于合成事件。九、useEffect 与 useLayoutEffect 区别维度useEffectuseLayoutEffect执行时机浏览器绘制后异步浏览器绘制前同步阻塞渲染否是使用场景多数副作用数据获取、订阅、日志需要测量DOM、同步修改样式SSR支持完全支持有警告需跳过// useLayoutEffect典型场景测量DOMuseLayoutEffect((){constheightdivRef.current.offsetHeightsetHeight(height)// 在绘制前更新避免闪烁},[])// useEffect数据获取useEffect((){fetchData().then(setData)},[])原则优先使用useEffect只有当需要在绘制前同步操作如测量DOM、防止闪烁时才用useLayoutEffect。十、React任务调度与优先级回答思路React的调度器Scheduler实现了基于优先级的任务调度。优先级分类从高到低Immediate同步任务立即执行如用户输入UserBlocking用户交互点击、按键Normal普通更新setStateLow低优先级数据预加载Idle空闲任务日志上报调度机制任务根据优先级进入不同队列每帧16.6ms执行任务剩余时间用requestIdleCallback执行低优先级任务高优先级任务可中断低优先级任务// 简化理解functionworkLoop(deadline){while(有任务deadline.timeRemaining()0){执行任务()}if(有任务)requestIdleCallback(workLoop)}十一、瀑布流布局实现回答思路多列布局每项高度不同依次放入最短列。实现方案CSS Multi-columncolumn-count: 3简单但无法精确控制顺序绝对定位 JS计算每列高度动态定位每个元素// JS瀑布流functionwaterfall(container,items,colCount3){constcolHeightsnewArray(colCount).fill(0)items.forEach(item{// 找到高度最小的列constminColcolHeights.indexOf(Math.min(...colHeights))item.style.positionabsoluteitem.style.left${minCol*(item.offsetWidth10)}pxitem.style.top${colHeights[minCol]}pxcolHeights[minCol]item.offsetHeight10})container.style.height${Math.max(...colHeights)}px}优化使用IntersectionObserver实现图片懒加载避免一次性加载所有图片。十二、长列表渲染优化方案回答思路参考之前面经。核心方案虚拟滚动只渲染可视区域react-window、vue-virtual-scroller分页/无限滚动滚动触底加载更多时间分片requestIdleCallback分批渲染复用DOMReact.memo、v-memo避免重渲染十三、大图/大量计算如何避免阻塞主线程回答思路将耗时任务移到主线程之外。方案方案适用场景原理Web Worker大量计算数据处理、图像处理独立线程通过postMessage通信OffscreenCanvas图像处理在Worker中操作CanvasWebAssembly高性能计算视频/音频编解码接近原生的执行速度任务分片需要与UI交替执行setTimeout/requestIdleCallback拆分// Web Worker示例// worker.jsself.onmessage(e){constresultheavyCalculation(e.data)self.postMessage(result)}// 主线程constworkernewWorker(worker.js)worker.postMessage(largeData)worker.onmessage(e)setResult(e.data)十四、Zustand 与 Redux 区别维度ReduxZustand学习曲线陡峭action、reducer、store平缓create函数代码量多需定义action type、reducer少直接修改state中间件丰富redux-thunk、redux-saga简单subscribe性能需手动优化reselect自动优化selector体积较大小~1kbDevTools完善支持需配置// Zustand示例import{create}fromzustandconstuseStorecreate((set)({count:0,increment:()set((state)({count:state.count1}))}))// Redux示例constcounterSlicecreateSlice({name:counter,initialState:{count:0},reducers:{increment:(state){state.count}}})选择建议中小型项目用Zustand大型项目/团队标准化用Redux Toolkit。十五、全局异常捕获与上报SDK设计回答思路设计一个框架无关的错误监控SDK。核心功能异常捕获window.onerror、unhandledrejection、try/catch包装数据聚合收集错误信息消息、堆栈、URL、用户行为、时间上报策略批量上报、sendBeacon、避免影响主线程去重相同错误在短时间内只上报一次上下文扩展支持自定义标签用户ID、版本号classErrorMonitor{constructor(options{}){this.appIdoptions.appIdthis.reportUrloptions.reportUrlthis.queue[]this.init()}init(){// 捕获JS错误window.onerror(message,source,lineno,colno,error){this.capture(js_error,{message,source,lineno,colno,stack:error?.stack})}// 捕获未处理的Promise拒绝window.addEventListener(unhandledrejection,(event){this.capture(promise_error,{reason:event.reason?.stack||event.reason})})// 监听页面关闭发送剩余队列window.addEventListener(beforeunload,()this.flush())}capture(type,data){this.queue.push({type,data,timestamp:Date.now(),url:location.href,userAgent:navigator.userAgent,appId:this.appId})// 批量上报队列满或定时发送if(this.queue.length10)this.flush()if(!this.timer)this.timersetTimeout(()this.flush(),3000)}flush(){if(this.queue.length0)returnconstdata[...this.queue]this.queue[]// 使用sendBeacon保证页面关闭时也能发送navigator.sendBeacon(this.reportUrl,JSON.stringify(data))if(this.timer)clearTimeout(this.timer)this.timernull}// 手动上报report(error,extra{}){this.capture(custom_error,{message:error.message,stack:error.stack,...extra})}}// 框架集成示例Vueapp.config.errorHandler(err,vm,info){monitor.capture(vue_error,{message:err.message,stack:err.stack,info})}设计要点解耦不依赖任何框架提供插件机制Vue/React集成可配置采样率、上报地址、自定义字段性能批量上报、异步发送、避免阻塞隐私脱敏处理不上报敏感信息知识点速查表知识点核心要点HTML5语义化header/nav/main/article/section/footerSEO可访问性SEO优化标题/描述、语义化标签、性能、sitemap、结构化数据TS防御性编程严格模式、unknown替代any、可选链、穷尽性检查interface vs typeinterface可合并、可扩展type适用联合/元组Parameters提取函数参数类型用于二次封装事件委托利用冒泡父元素监听减少内存React事件顺序原生事件先于合成事件useEffect vs useLayoutEffect绘制后/前大多数用useEffectReact调度优先级队列高优先级可中断低优先级瀑布流最短列动态定位CSS多列或JS计算长列表优化虚拟滚动、分页、时间分片Web Worker独立线程处理耗时任务Zustand vs ReduxZustand轻量Redux规范适合大型项目异常监控SDK捕获error/unhandledrejection批量上报框架解耦 最后一句正泰电气这场实习一面是一份“进阶版”的基础面经。从TS高级类型、React调度机制到瀑布流、Web Worker再到异常监控SDK设计难度层层递进。面试官显然不满足于“会不会用”而是考察是否理解原理、能否设计解决方案。能从容应对这套题说明你不仅会写业务代码更具备工程化思维和系统设计能力。这样的能力正是大厂实习面试中拉开差距的关键。