面经-05

5 阅读16分钟

一. 讲一下浏览器的 Event Loop 机制,宏任务和微任务的执行顺序是怎样的? setTimeout和 Promise 的执行顺序有什么区别?

  • Event Loop 机制:浏览器执行 JS 的单线程机制,任务分为宏任务(macro task)和微任务(micro task)。

    1. 执行栈为空时,取一个宏任务执行(比如 script、setTimeout、setInterval、I/O 回调)。
    2. 宏任务执行过程中产生的微任务会立即执行(Promise.then、MutationObserver)。
    3. 当前宏任务执行完毕后,执行微任务队列,直到清空。
    4. 清空微任务后,渲染更新(repaint/reflow),然后取下一个宏任务。
  • 执行顺序示例

console.log('script start');

setTimeout(() => console.log('setTimeout'), 0);

Promise.resolve().then(() => console.log('promise1'))
               .then(() => console.log('promise2'));

console.log('script end');

输出顺序:

script start → script end → promise1 → promise2 → setTimeout
  • 原因:微任务优先于下一个宏任务执行;setTimeout 是宏任务。

二. CSS 中,position 有哪些值? 它们分别是根据什么定位的?

  1. static:默认值,不做特殊定位,按照文档流排列。
  2. relative:相对定位,相对于自身在文档流中的原位置进行偏移。
  3. absolute:绝对定位,相对于最近的已定位祖先元素(非 static)进行定位,脱离文档流。
  4. fixed:固定定位,相对于视口定位,脱离文档流,滚动不动。
  5. sticky:粘性定位,基于滚动位置在 relative 与 fixed 之间切换。

三. Webpack 和 Vite 有什么区别? 为什么 Vite 的开发环境启动速度会快很多?

  • Webpack:打包器(bundler),构建时将所有模块打包成一个或多个 bundle。

    • 开发模式:每次变更都需要重新打包整个依赖图,慢。
  • Vite:原生 ES Module + Rollup 打包器,利用浏览器原生模块化。

    • 启动快:不打包整个应用,浏览器按需请求模块(按需加载 ES module),只编译实际访问的模块。
    • 热更新快:模块级别 HMR,不刷新整个页面。

四. 你对前端工程化的理解,除了构建工具,还包括哪些?

  • 构建工具:Webpack、Vite、Rollup
  • 包管理:npm、yarn、pnpm
  • 模块化开发:ES Modules / CommonJS
  • 自动化:脚本化任务、CI/CD
  • 代码规范:ESLint、Prettier
  • 测试:单元测试、集成测试
  • 监控与性能分析:前端监控、RUM、Lighthouse
  • 部署和版本管理:CDN、灰度发布、版本控制(git)

五. 我看你简历里这个项目挺复杂的,能具体展开讲一下吗? 你在其中扮演了什么角色,解决了哪些核心的技术难题?

  • 项目描述:例如大型电商 SPA,包含商品浏览、购物车、支付、后台管理。

  • 个人角色:前端主开发/架构设计。

  • 核心技术难题

    • 大型状态管理(Redux/Context/Observable)
    • 性能优化(首屏加载、虚拟列表、懒加载)
    • 模块拆分与路由懒加载
    • 跨域与接口统一封装
    • 异常监控(白屏、Promise 错误、接口失败重试)

六. 如果要从零设计大型电商网站的前端架构,你会如何进行技术选型?需要考虑哪些方面?

  1. 技术选型:React/Vue/TS + Webpack/Vite + Node.js 后端 + GraphQL/REST

  2. 考虑方面

    • 团队熟悉程度
    • 可维护性和可扩展性
    • 性能优化空间
    • 组件库和开发效率
    • SSR/SEO 需求
    • 状态管理方案(Redux/MobX/Vuex/Pinia)
    • 构建和部署方案(CI/CD、CDN、缓存策略)

七. 微前端了解吗? 讲讲主流实现方式及优缺点,你在项目里用过吗?效果如何?

  • 实现方式

    1. iframe 沙箱:简单隔离,但性能差、通信复杂
    2. JS/CSS 沙箱(如 single-spa):多个子应用独立加载,较高灵活性
    3. Webpack Module Federation:共享依赖,按需加载,体积小
  • 项目实践:使用 single-spa,将购物车和商品列表拆分为微应用,实现独立部署与团队协作,用户感知无明显差异。


八. 项目里状态管理如何选型? Redux、MobX 或其他方案,它们的核心设计思想是什么?

  • Redux:单一状态树 + 不可变数据 + action + reducer。适合复杂应用,需要严格数据流。
  • MobX:响应式编程,状态可变但自动追踪依赖,适合中小型或频繁更新的应用。
  • 选型考虑:状态复杂度、团队熟悉程度、调试工具支持、性能要求。

九. 讲一下 React Fiber 架构,它解决了什么问题? 相比 Stack Reconciler 的变化?

  • 问题:Stack Reconciler 同步渲染,阻塞主线程,长任务影响用户体验。

  • Fiber 架构:将渲染任务拆成小单元(Fiber 节点),支持可中断渲染、优先级调度和增量更新。

  • 变化

    • 支持时间切片(Time Slicing)
    • 支持并发模式(Concurrent Mode)
    • 更新过程可暂停、恢复和优先级调度

十. 项目中如何处理异常和监控?JS 错误、白屏问题、性能数据如何收集和上报?

  • 方法

    • JS 错误:window.onerror / window.addEventListener('unhandledrejection')
    • 白屏:监听页面 DOMContentLoaded / 首屏渲染情况
    • 接口错误:fetch / axios 拦截器
    • 性能数据:Performance API / Lighthouse / RUM
  • 上报方式:日志上报到后台服务或第三方监控平台(Sentry、RUM)


十一. 如果页面加载很慢,你会从哪些方面排查和优化?

  • 网络:Bundle 体积、请求数量、CDN、gzip/brotli
  • 资源:图片/字体优化,懒加载
  • JS 执行:长任务优化,虚拟列表,异步加载
  • 渲染:减少重绘重排,CSS 优化
  • 缓存:HTTP cache、Service Worker
  • 监控:Lighthouse、Chrome DevTools、RUM

十二. 从浏览器输入一个 URL 到页面完整展示,中间发生了什么?

1. 概念

浏览器从输入 URL 到页面渲染完成是一个完整的请求、处理、渲染流程,涉及网络、HTTP 协议、浏览器渲染引擎、JS 执行等多个环节。

2. 原理/流程

  1. DNS 解析

    • 浏览器检查缓存(DNS cache / OS cache / router cache)
    • 未命中则向 DNS 服务器请求解析域名到 IP
  2. TCP 连接

    • 建立三次握手:SYN → SYN-ACK → ACK
    • 确认客户端与服务器可通信
  3. TLS 握手(HTTPS)

    • 协商加密算法和密钥
    • 建立加密通道保证通信安全
  4. HTTP 请求

    • 浏览器发送 GET/POST 请求
    • 带上请求头(Cookie、User-Agent、Referer 等)
  5. 服务器处理

    • 解析请求 → 数据库查询 → 构建响应
    • 返回 HTML / CSS / JS / 图片资源
  6. 浏览器解析 HTML

    • 生成 DOM 树
    • 遇到外部 CSS/JS,会阻塞渲染或异步加载
  7. 解析 CSS

    • 生成 CSSOM 树
    • CSSOM + DOM → Render Tree
  8. 布局(reflow)

    • 计算每个元素的尺寸和位置
  9. 绘制(paint)

    • 根据 render tree 绘制像素
  10. JS 执行

    • 解析、编译、执行 JS
    • 可能操作 DOM / CSSOM → 触发二次 reflow/repaint
  11. 资源加载

    • 图片、字体、异步请求等按需加载
  12. 完成渲染

    • 用户看到完整页面

3. 示例/优化点

  • 首屏渲染慢 → 可使用 SSR 或 Code Splitting
  • 大 JS 文件 → 异步加载 + Tree-shaking
  • 图片 → 懒加载,使用 WebP

十三. HTTP 常见状态码有哪些?301 和 302 的区别?

1. 概念

HTTP 状态码用来表示请求结果。分为五类:1xx、2xx、3xx、4xx、5xx。

2. 详细分类

  • 1xx 信息性:100 Continue
  • 2xx 成功:200 OK, 201 Created
  • 3xx 重定向:301 Moved Permanently, 302 Found, 304 Not Modified
  • 4xx 客户端错误:400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found
  • 5xx 服务器错误:500 Internal Server Error, 502 Bad Gateway

3. 301 vs 302

  • 301:永久重定向,浏览器会缓存,SEO 会更新索引
  • 302:临时重定向,浏览器不更新 SEO 索引

4. 实践/注意事项

  • 重定向链过长会影响性能
  • 使用 301 替换永久域名或 HTTPS 转换
  • 使用 302 临时维护或 A/B 测试

十四. 盒模型理解,标准盒模型和 IE 盒模型区别,如何切换?

1. 概念

  • 盒模型:每个元素在页面上占用的空间由 content + padding + border + margin 构成
  • 标准盒模型(content-box):width/height 只计算 content
  • IE 盒模型(border-box):width/height 包含 content + padding + border

2. 原理

  • 浏览器渲染元素时,先计算 content → padding → border → margin
  • 标准模型和 IE 模型差异会导致布局计算不一致

3. 示例

/* border-box 模型 */
* {
  box-sizing: border-box;
}
  • 适合现代布局,因为设置宽度不受 padding/border 影响

4. 注意事项

  • Flex/Grid 布局建议使用 border-box
  • IE8 以下需兼容写法

十五. 实现三栏布局,两边固定,中间自适应,有几种方法?

1. 概念

三栏布局常用于网站:左右固定宽度导航/广告栏,中间自适应内容区域。

2. 方法/原理

  1. Flexbox(一维布局)

    • 左右固定宽度,中间 flex:1
    • 优势:响应式、简洁
  2. CSS Grid(二维布局)

    • grid-template-columns 定义列宽
    • 优势:复杂布局更直观
  3. float + margin(传统方法)

    • 左右浮动,中间 margin 自动撑开
    • 注意清除浮动

3. 示例

/* Flexbox */
.container { display: flex; }
.left, .right { width: 200px; }
.center { flex: 1; }

/* Grid */
.container { display: grid; grid-template-columns: 200px 1fr 200px; }

4. 注意事项

  • Flexbox 默认主轴是 row,可调整为 column
  • Grid 可以设置 gap,避免额外 margin/padding

十六. display: none 与 visibility: hidden 的区别

1. 概念

  • display: none:元素完全移除,不占空间
  • visibility: hidden:元素隐藏,但仍占空间

2. 原理

  • display 会触发 layout 变化
  • visibility 仅影响绘制,不触发布局改变

3. 示例

.hidden1 { display: none; }
.hidden2 { visibility: hidden; }

4. 注意事项

  • 动画:visibility 可以与 opacity 配合渐隐显示
  • layout 依赖:display:none 会影响后续元素位置

十七. JavaScript 基本数据类型,null 与 undefined 区别

1. 基本类型

Number, String, Boolean, Symbol, BigInt, undefined, null

2. 原理

  • JS 变量分为基本类型(值类型)和引用类型(对象、数组、函数)
  • 内存分配:基本类型存栈,引用类型存堆,栈存指针

3. null vs undefined

  • undefined:声明未赋值的变量
  • null:程序员手动赋的“空对象”占位

4. 示例

let a;          // undefined
let b = null;   // null

5. 注意事项

  • typeof null → "object"(历史遗留)
  • null == undefined → true, null === undefined → false

十八. 原型、原型链,proto 和 prototype

1. 概念

  • 每个 JS 对象都有 __proto__ 指向其构造函数的 prototype
  • prototype 是函数对象特有,用于实例继承属性

2. 原理

  • 属性查找:先自身属性 → 原型链
  • 原型链形成继承机制

3. 示例

function Person(name){ this.name = name; }
Person.prototype.say = function(){ console.log(this.name); }
const p = new Person('Tom');
p.say(); // Tom
console.log(p.__proto__ === Person.prototype); // true

4. 注意事项

  • 修改原型会影响所有实例
  • proto 可动态修改继承链,但不推荐

十九. 手写深拷贝函数

1. 原理

  • 递归复制对象和数组
  • 处理循环引用 → 使用 WeakMap 缓存
  • 拷贝特殊对象(Date, RegExp, Map, Set 等)

2. 示例

function deepClone(obj, map = new WeakMap()) {
  if (obj === null || typeof obj !== 'object') return obj;
  if (map.has(obj)) return map.get(obj);

  let clone = Array.isArray(obj) ? [] : {};
  map.set(obj, clone);

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) clone[key] = deepClone(obj[key], map);
  }
  return clone;
}

3. 注意事项

  • 函数不拷贝
  • 循环引用必须处理

二十. const 与 var 区别,暂时性死区(TDZ)

1. 概念

  • var:函数作用域,变量提升,可重复声明
  • let/const:块作用域,不可重复声明,存在 TDZ

2. TDZ 原理

  • 变量在声明之前无法访问,访问会报错
  • 编译阶段识别 let/const 未初始化状态

3. 示例

console.log(a); // undefined
var a = 1;

console.log(b); // ReferenceError
let b = 2;

二十一. 最近使用过的前端框架,为什么选择

1. React + TypeScript

  • React:组件化、虚拟 DOM、生态丰富
  • TypeScript:类型安全、智能提示

2. Vue

  • 响应式系统、模板语法、轻量、开发效率高

3. 注意事项

  • 项目复杂度、团队熟悉度、生态决定选择

二十二. React 中优化大列表渲染性能

1. 问题

  • 数百/千条数据渲染 → 性能低,DOM 节点过多

2. 优化方法

  • 虚拟列表(react-window / react-virtualized)
  • React.memo / useMemo 避免重复渲染
  • 合理 key 避免重新挂载

3. 示例

const Item = React.memo(({data}) => <li>{data}</li>);

二十三. Vue3 与 Vue2 重要改进

  • Proxy 响应式,比 defineProperty 完整
  • Composition API,逻辑复用更方便
  • Fragment、Teleport、Suspense
  • 性能优化、Tree-shaking 支持

二十四. 使用 Web Workers 提高性能

  • 将耗时 JS 运算放到 Worker 线程
  • 主线程保持 UI 流畅
  • 示例:
const worker = new Worker('worker.js');
worker.postMessage(data);
worker.onmessage = e => console.log(e.data);

二十五. CSS Grid 和 Flexbox 解决布局问题

  • Flexbox:一维布局,适合列表、导航
  • Grid:二维布局,复杂网格布局

二十六. JS Event Loop,宏任务与微任务

  • 宏任务:script、setTimeout、setInterval
  • 微任务:Promise.then、MutationObserver
  • 执行顺序:执行栈空 → 微任务队列 → 渲染 → 下一个宏任务

二十七. 模块加载器原理

  • 定义模块与依赖
  • 静态分析依赖顺序
  • 缓存已加载模块

二十八. 静态站点生成器原理及选择

  • 构建时生成 HTML → 部署静态资源
  • SEO 优化
  • 选择:Gatsby/Next.js(React),Hugo/Hexo(内容驱动)

二十九. 前端依赖管理与优化

  • npm/yarn/pnpm
  • Tree-shaking
  • 按需加载
  • CDN 或 externals 减少 bundle

三十. SSR 与 CSR 的差异

1. 概念

  • CSR(Client Side Rendering) :浏览器下载 HTML + JS,JS 运行后生成 DOM,渲染页面。
  • SSR(Server Side Rendering) :服务器直接返回带内容的 HTML,浏览器只需解析即可。

2. 原理

  • CSR

    1. 浏览器收到 HTML 骨架(无内容)
    2. 下载 JS → 执行 → 生成 DOM → 页面可见
  • SSR

    1. 服务器运行框架(如 Next.js / Nuxt.js)
    2. 生成完整 HTML 返回
    3. 浏览器展示内容 → JS 接管交互(hydrate)

3. 区别

对比项CSRSSR
首屏加载慢(依赖 JS 执行)快(直接返回 HTML)
SEO好(爬虫能抓 HTML)
交互体验后续快可能需要 hydrate 时间
适用场景管理后台、工具类应用电商、新闻门户、博客

4. 示例

Next.js SSR 页面:

export async function getServerSideProps() {
  const res = await fetch('https://api.example.com/posts');
  const posts = await res.json();
  return { props: { posts } };
}

三十一. XSS 与 CSRF 防护

1. XSS(跨站脚本攻击)

  • 原理:恶意脚本注入网页,在用户浏览时执行。

  • 类型

    • 存储型(恶意代码存数据库,反射给用户)
    • 反射型(拼接 URL 参数直接执行)
    • DOM 型(前端代码执行 eval / innerHTML 等)

2. 防护措施

  • 输出内容做转义(<&lt;
  • CSP(内容安全策略)限制脚本来源
  • 禁用 evalinnerHTML

3. CSRF(跨站请求伪造)

  • 原理:用户已登录,攻击者诱导发起请求,利用 Cookie 自动带上。

4. 防护措施

  • CSRF Token(后端生成随机数,前端提交时校验)
  • SameSite Cookie 属性(禁止跨站携带)
  • Referer / Origin 校验

三十二. WebSockets 实时通信

1. 概念

  • HTTP:请求/响应模式,单向
  • WebSocket:全双工通信,浏览器和服务器能随时互发消息

2. 原理

  1. 客户端发起 Upgrade: websocket 请求
  2. 服务器返回 101 Switching Protocols
  3. 双方切换到 WebSocket 协议

3. 示例

const ws = new WebSocket("wss://example.com/socket");

ws.onopen = () => ws.send("hello");
ws.onmessage = e => console.log("收到:", e.data);
ws.onclose = () => console.log("连接关闭");

4. 应用场景

  • 实时聊天
  • 股票/体育比分推送
  • 游戏联机

三十三. PWA(渐进式 Web 应用)

1. 核心优势

  • 可离线访问(Service Worker 缓存资源)
  • 类似原生 App(安装到桌面,启动无地址栏)
  • 支持消息推送(Push API)

2. 转化步骤

  1. 添加 manifest.json(图标、启动页、主题色等)
  2. 注册 Service Worker(缓存 + 拦截请求)
  3. 全站 HTTPS

3. 示例

navigator.serviceWorker.register('/sw.js');

三十四. 代码可维护性保证

1. 方法

  • 组件化:拆分 UI 模块
  • 模块化:逻辑拆分成 utils / services
  • 规范化:ESLint + Prettier 强制风格
  • 类型安全:TypeScript
  • 测试保障:单元测试 + 集成测试

2. 原理

保证项目多人协作时,修改某一部分不会影响整体。


三十五. 单元测试重要性与框架

1. 重要性

  • 快速发现 bug
  • 防止回归(改代码导致旧功能失效)
  • 提升代码可维护性

2. 常用框架

  • Jest(最常用,Facebook 出品)
  • Vitest(Vite 生态)
  • Mocha + Chai(灵活组合)
  • React Testing Library(React 组件测试)

3. 示例

test('加法函数', () => {
  expect(add(1, 2)).toBe(3);
});

三十六. 快速学习新技术经验

1. 方法论

  1. 先读官方文档 → 掌握核心概念
  2. 动手写 demo → 验证理解
  3. 遇到问题查源码/issue → 深入机制
  4. 总结输出文章 → 加深记忆

三十七. 页面加载慢优化思路

1. 网络层面

  • CDN 加速
  • 压缩资源(gzip/br)
  • 按需加载、懒加载

2. 浏览器渲染

  • 减少重排/重绘
  • 使用 requestAnimationFrame

3. 代码层面

  • Tree-shaking
  • 代码分割(Code Splitting)

4. 监控工具

  • Chrome DevTools
  • Lighthouse

三十八. Tree Shaking 原理

1. 概念

  • 去掉未使用的代码,减小 bundle

2. 原理

  • 依赖 ES Module 静态导入
  • 构建工具(Webpack, Rollup, Vite)在编译阶段分析引用关系

3. 示例

// util.js
export function used() {}
export function unused() {}

// index.js
import { used } from './util.js';
used();

构建后只保留 used()


三十九. 前端安全实践

1. 主要风险

  • XSS(跨站脚本)
  • CSRF(跨站请求伪造)
  • 点击劫持(iframe 嵌套攻击)
  • 依赖漏洞

2. 实践

  • 输入校验 & 输出转义
  • CSP + SameSite Cookie
  • iframe sandbox 属性
  • 定期升级依赖(npm audit fix)

四十. 新技术/工具决策过程

1. 考量点

  • 成熟度(是否有大公司使用)
  • 社区活跃度(更新频率、Issue 响应)
  • 团队熟悉度(是否已有经验)
  • 长期维护成本

2. 示例

决定是否上 Redux Toolkit → 评估现有项目状态管理复杂度、团队熟悉程度。


四十一. CI/CD 流程

1. CI(持续集成)

  • 每次提交 → 自动构建、跑测试、静态检查
  • 保证主分支稳定

2. CD(持续交付/部署)

  • 通过 CI 构建产物 → 自动发布到服务器 / CDN

3. 工具

  • GitHub Actions
  • GitLab CI
  • Jenkins

四十二. 可访问性(Accessibility)

1. 概念

让残障人士也能使用网页。

2. 实践

  • 提供语义化标签(<button> 而不是 <div>
  • 为图片加 alt
  • 提供键盘操作支持(tabindex)
  • 对比度达标(WCAG 标准)

四十三. TypeScript 优势与应用

1. 优势

  • 类型检查,减少 bug
  • 更好的 IDE 提示
  • 重构安全性高

2. 应用场景

  • 中大型项目
  • 团队协作

3. 示例

function add(a: number, b: number): number {
  return a + b;
}

四十四. 前端状态管理

1. 常见方案

  • Redux(单向数据流,可预测)
  • MobX(响应式,学习成本低)
  • Vuex / Pinia(Vue 专属)
  • React Query / SWR(数据请求状态管理)

2. 选型思路

  • 项目规模小:useState / useReducer
  • 中型:MobX / Pinia
  • 大型:Redux Toolkit

四十五. 大规模 CSS 优化

1. 问题

  • 样式冲突
  • 体积过大

2. 方案

  • BEM 命名规范
  • CSS Modules / CSS-in-JS
  • 预处理器:SCSS/LESS
  • PostCSS 自动优化
  • 按需加载:移除未用 CSS(PurgeCSS)

四十六. 前端监控工具

1. 错误监控

  • Sentry, Bugsnag → 捕获 JS 异常,堆栈上报

2. 性能监控

  • Performance API 收集首屏、白屏时间
  • Lighthouse

3. 用户行为

  • RUM(Real User Monitoring)
  • 采集页面点击、路径、停留时间

四十七. 浏览器兼容性处理

1. 方法

  • Autoprefixer:自动加浏览器前缀
  • Babel:转译 ES6+ 语法
  • Polyfill:填充新特性(如 Promise, fetch)
  • Graceful degradation(优雅降级)
  • Progressive enhancement(渐进增强)