面灵AI→

放生面经-经纬恒润前端一面

时间
2026-10
来源
牛客网

《面试题目》

  1. 确认学校、专业、应聘岗位,以及实习经历和各自负责的业务。
  2. 学习前端多长时间了?是否了解前端工程化?
  3. 在校成绩排名如何?参加过哪些竞赛、项目,取得了什么成绩?英语六级成绩如何?
  4. 什么是页面回流(重排)和重绘?二者有什么关系?
  5. 哪些操作会触发回流?怎样减少回流和重绘?(追问:怎样批量修改样式?为什么动画常用 transform?)
  6. CSS 的 position 有哪些取值?(追问:static、relative、absolute、fixed、sticky 分别有什么特点?)
  7. 相对定位和绝对定位有什么区别?(追问:绝对定位相对谁定位?二者是否脱离文档流、是否保留原空间?)
  8. 水平垂直居中有哪些方案?Flex、Grid、绝对定位加 transform 分别怎样写?还有哪些适用特定场景的方案?
  9. 什么是闭包?为什么外层函数执行结束后,内部函数仍能访问外层变量?
  10. 在什么实际场景使用过闭包?闭包有什么用途和风险?闭包一定会导致内存泄漏吗?
  11. 数组常用方法有哪些?哪些会修改原数组,哪些不会?(追问:splice 的参数和返回值是什么?它与 slice 有什么区别?)
  12. 浏览器端常见存储方式有哪些?(追问:Cookie、localStorage、sessionStorage 和服务端 Session 在位置、容量、生命周期、请求携带方式及安全性上有什么区别?)
  13. 低代码任务组件是怎样设计的?怎样同步最新状态?
  14. 反问。

《参考解析》

回流与重绘的关系。浏览器的渲染大致分「构建 DOM/CSSOM → 计算样式 → 布局(Layout,也就是回流/重排)→ 绘制(Paint,也就是重绘)→ 合成上屏」几步。回流是几何信息变化后重新计算元素的位置和尺寸,代价最高,因为它会顺着渲染树向下影响子节点、还可能牵连后续兄弟节点;重绘是颜色、背景、可见性这类不影响几何的属性变化后重新画一遍。二者的关系是包含关系:回流必然引起重绘,重绘不一定触发回流。触发回流的操作很典型——增删 DOM、改变宽高/内外边距/字体大小、读取 offsetTop、scrollTop、getComputedStyle 这类会强制刷新布局队列的属性,甚至只是改变窗口大小。减少的手段就是三件事:把多次样式修改合并(用 class 一次性切换,或者先用 display:none 离线处理再显示)、用 DocumentFragment 或字符串批量构建再一次性插入、以及把只做视觉变化的动画交给 transform / opacity。追问「为什么动画常用 transform」,正是因为它只改变合成层属性,不进入布局和绘制阶段,只做合成(Composite),甚至能提升为独立图层交给 GPU 处理,比改 left/top 流畅得多;如果确实要提前提层,可以用 will-change: transform,但不能滥用,图层太多反而吃显存。

position 五种取值与定位参照。static 是默认值,元素在正常文档流里,top/left/z-index 对它无效。relative 保留原有的文档流占位,相对「自己原本的位置」偏移,所以移动后原来的空间还在,常用于给子元素做定位参照。absolute 完全脱离文档流、不保留原空间,定位参照是「最近的已定位祖先」(position 不为 static 的祖先),找不到就退到初始包含块;因此工程上最稳的写法是「父相子绝」。fixed 同样脱离文档流,但参照的是视口,滚动时不跟随,除非祖先有 transform/filter/perspective 这类属性——那时它会被降级成相对该祖先定位,这是非常隐蔽的坑。sticky 是相对定位和固定定位的混合:在阈值内按相对定位表现、保留占位,超过阈值后黏在容器的滚动边界上;它生效的前提是祖先链上没有 overflow: hidden/auto/scroll 把它裁掉,而且必须显式指定 top/bottom/left/right 之一,否则和 relative 没区别。答题时把「是否脱离文档流、是否保留原空间、参照谁」这三列讲清楚,比背定义得分高。

水平垂直居中的方案谱系。Flex 最省事:父容器 display:flex; justify-content:center; align-items:center,单行多行都适用。Grid 更短:display:grid; place-items:center(或者给子项 place-self:center)。绝对定位加 transform 适用于子元素尺寸未知的场景:position:absolute; left:50%; top:50%; transform:translate(-50%,-50%),用 translate 的百分比是相对自身尺寸算的,所以不需要知道宽高;如果尺寸已知,也可以配 margin 负值或 inset:0; margin:auto。特定场景的方案还有:单行文本用 line-height 等于容器高度,行内块配合 vertical-align:middle 加一个零宽度的基线占位元素,table-cell 配 vertical-align:middle(老项目兼容写法)。答题时补一句「margin: auto 在 Flex 里能吃掉剩余空间、transform: translate(-50%,-50%) 会带来半个像素的模糊」,能体现真写过。

闭包的本质与风险。闭包不是一个语法特性,而是作用域链的自然结果:函数在创建时会把外层作用域的变量对象记进自己的 [[Scope]],只要这个函数还被引用,它引用的那部分外层环境就不会被回收,所以外层函数栈帧虽然退出了,变量对象仍留在堆上,内部函数照样能访问。它最常见的用途是封装私有状态(计数器、防抖节流里保存定时器 id 和上次执行时间)、回调里固定循环变量、以及模块化时暴露有限的接口。风险是「引用被意外长期持有」:如果闭包挂在全局事件监听、定时器或长生命周期的对象上,对应的 DOM 和整条作用域链都会被留住。但要说清楚——闭包本身不会必然泄漏,只有当被捕获的环境确实不再需要、却仍然可达时才是泄漏,解决方式是把不再用的引用置空、及时解绑监听与清理定时器。

数组方法与浏览器存储。会改原数组的:push/pop/shift/unshift、splice、sort、reverse、fill、copyWithin;不改原数组的:slice、concat、map/filter/reduce/forEach/some/every/find、join、flat、includes/indexOf。splice(start, deleteCount, ...items) 从 start 开始删 deleteCount 个并插入新项,返回值是被删除元素组成的数组(没删就是空数组),它改原数组;slice(start, end) 只截取、左闭右开、不改原数组。存储侧:Cookie 存在浏览器里、单个约 4KB、会随同域请求自动带上、可通过 HttpOnly/Secure/SameSite 加固,是唯一能天然被服务端读到的;localStorage 约 5MB、同源共享、除非主动清除否则永久;sessionStorage 容量相同但只活在当前标签页的会话里,关闭即消失,二者都不会随请求发送,因此存 token 时要额外防 XSS;服务端 Session 存在服务器(内存/Redis),浏览器只持有 sessionId,容量不受前端限制但要考虑服务端存储与集群共享。更大的结构化数据用 IndexedDB,需要缓存请求响应用 Cache Storage/Service Worker。

低代码任务组件的设计。通行做法是「schema 驱动 + 单向数据流」:组件的结构、字段、校验和交互由一份 JSON 配置描述,渲染层只做解释执行,属性面板改的是这份 schema 而不是直接改 DOM。状态同步的关键是定清「谁是唯一数据源」:运行时数据放统一的 store(或表单引擎的状态树),组件只读、变更通过 action 回写,避免同一份数据存在多份副本。多端/多组件共享时用发布订阅——状态变更后广播版本号或 diff,各订阅者按需重渲染;跨页或跨端则用一份带版本号的服务端数据做锚点,冲突时以版本较新的一方为准并给出提示。顺带要处理两件事:配置的版本兼容(老 schema 能升到新结构)和撤销重做(本质是把状态快照或操作日志存成栈)。