前端基础大厦

前端知识体系梳理

一、函数式编程

1. 核心特性:不可变

  • 数据不可更改,React 的 state、reducer 都要求遵循该原则;简化操作需要借助 immer 这类工具
  • 为什么用:正因为数据不可变,所以需要复制产生新的对象;复杂对象复制更新较为繁琐,因此使用工具库简化
  • 优势:可预测、可测试、可维护、具备确定性;React 内部是浅比较(引用比较),如果直接修改会导致渲染异常

2. 纯函数

  • 定义:确定的输入,产生确定的输出,并无副作用(没有修改外部变量这类与当前函数功能无关的操作)
  • 注意事项:不要随便引入全局变量,不要引入可变数据,尽可能保障确定性
  • 价值:解决可测试性、可维护性,保障工程中的确定性
  • 相关应用:React 纯函数、reducer 需要掌握

3. 相关工具库

  • lodash(需掌握)
  • immer
  • date-fns

4. 单向数据流

  • 数据流向单一可控:props 只读,只能由父传子并改变,除非通过回调传入改变函数

5. 组合思想

  • 一般组合优于继承
  • 单一职责、低耦合
  • 继承:耦合度高,父类的改变可能会影响其余所有子类

6. 高阶函数

  • 本质是装饰器的思想
  • 定义:传入函数或者返回一个函数
  • 应用场景:
    • 链式调用
    • 偏函数
    • 柯里化
    • compose 中间件的思路
    • 装饰器这类

7. 声明式写法

二、输入 URL 发生了什么

1. URL 解析

  • 目的:路径补全、检测、缓存,便于后续解析域名

2. 域名解析(DNS)

  • 递归查询
  • 迭代查询

3. 网络传输分层

  • 应用层:开始 HTTP 传输,首先建立连接
  • 传输层:通过 TCP 建立连接,通过三次握手
  • 网络层:IP 协议,寻址,找唯一的 MAC 地址
  • 数据链路层
  • 物理层

4. 浏览器渲染

  • DOM 树构建
  • CSS 树构建
  • Render 渲染树构建
  • 布局(回流):计算位置等信息
  • 绘制:绘制可视图层
  • 合成层:发送以上信息到 GPU 合成层,进行屏幕显示

三、跨标签页通信

1. 解决的问题

解决同域、非同域标签页的通信问题

2. 技术选型

  • localStorage
    • 仅同域名
    • 容量有限制,只能存字符串
  • BroadcastChannel
    • 仅同源
    • 当前标签页可被广播
    • 支持对象等多种格式
    • 用法和 postMessage 类似:postMessage 发送,message 监听
    • 容量更大,取决于浏览器内存占用
  • postMessage
    • 支持跨域,项目中使用 iframe 时,可根据简洁、高效、跨域需求选择
    • 注意数据序列化与性能问题
  • SharedWorker
    • 可以被多个标签页共享的线程
    • 对比 Web Worker 只能在当前标签页使用
    • 可用于计算优化

四、Web Worker

1. 为什么用 Web Worker

  • 属于多线程 API
  • 浏览器允许开辟一个线程单独运行,不阻塞主线程

2. 目的

  • 解决主线程阻塞问题
  • 提升性能

3. 应用场景

  • 计算密集型:如大量的数据计算、图形处理;业务存在很多二次数据处理、特定算法处理,加快首屏渲染速度
  • 文件上传、导出场景:针对金融业务表格数据居多的场景,前端自己导出表格会占用较多内存和时间
  • 订阅大量实时行情:首屏加载需要处理大量实时数据

4. 弊端

  • 无法访问全局变量、DOM

五、浏览器存储

  • 请求会自动携带,包含服务器一些少量数据
  • 用于用户状态相关内容
  • 相关属性:
    • SameSite:防范跨站请求伪造(XSRF),禁止跨站携带;可配合 XSRF 双重 token 进行验证
    • Strict:严格模式
    • maxAge:过期时间
    • domain:限制/允许其他子域名访问
    • path:限制同域名的路径访问
    • HttpOnly:防范 XSS
    • Secure:仅 HTTPS 下携带

2. localStorage

  • 容量:5-10MB
  • 生命周期:永久,实践中会加入 TTL 过期控制
  • 支持同域共享,可通过 storage 事件监听变化
  • 适用场景:少量接口缓存(配备 TTL)以及用户的配置信息,提升用户体验

3. IndexedDB(异步)

  • 属于数据库级存储,异步,容量大,支持多类型内容存储
  • 适用场景:需要存储文档、图片等大容量内容时可用

4. sessionStorage

  • 容量:5-10MB
  • 生命周期:浏览器标签页关闭即消失
  • 仅同域可用

5. Token 与 Session 区别

  • session 存服务器,cookie 存浏览器
  • session 依赖 cookie,存在 CSRF 风险;token 放请求头中,更安全
  • token 支持跨域,session 仅同域

6. 相关问题

  • CSRF 为何 cookie 请求会被携带?不是不同域吗?
  • CSRF 如何防范

六、跨域

1. 本质

浏览器的安全限制,保障安全,禁止不同源脚本交互;同源要求协议、端口、域名完全一致

2. 解决策略

  • JSONP
    • 简单
    • 只支持 GET 请求,难以处理复杂数据,存在安全攻击风险(callback 注入)
  • CORS
    • OPTIONS 预检请求:复杂请求(PUT、DELETE、携带复杂请求头)会先发预检
    • 请求头:
      • Origin:标识请求源
      • Access-Control-Request-Method / Headers:告知服务端请求方法和请求头
    • 响应头:服务端返回 Access-Control-Allow-Origin / Headers 等
    • 浏览器判断是否允许跨域
    • 携带 cookie:通过 credentials(凭证)字段设置
      • sameOrigin:同域才携带
      • omit:跨域不携带
      • include:强制全部携带

七、前端安全

1. XSS(跨站脚本攻击)

  • 本质:向浏览器注入恶意脚本并执行
  • 分类:
    • 反射式:注入脚本到路径,被访问后窃取信息发送到服务器
    • 存储式:恶意脚本存储到服务器中
    • DOM 型:把危险脚本通过 JS 注入到 innerHTML 中执行
  • 防范:
    • 输入、输出转义:通过 dompurify,或直接转义
    • 转成 Markdown:AI 项目中为了兜底,先通过 markdown-it 进行了转义
    • 设置 Cookie 的 HttpOnly 属性,禁止 JS 读取
    • CSP 防护:设置请求头,控制加载资源,避免内联、非法资源加载

2. XSRF/CSRF(跨站请求伪造)

  • 原理:用户已登录状态下,点击攻击页面,向目标网站发起伪造请求
  • 本质:利用 cookie 在目标域请求中会自动携带的特性
  • 防范:
    • 双重 token 验证:利用跨域限制,攻击者无法获取具体 cookie 内容
    • SameSite:仅同站点才能携带 cookie
    • 验证码

3. 其他攻击

  • 点击劫持:通过 X-Frame-Options(deny、allow 等)禁止 iframe 嵌入加载,CSP 设置白名单链接
  • DDoS 攻击
  • 中间人攻击等

八、前端工程化

1. 工程化是什么

一套软件工程流程,包含开发、测试、优化、部署、监控、CI/CD 等体系化工程

  • 解决的问题:降低开发成本,提升工程效率,以及扩展性、稳定性等

2. 模块化

  • 核心思想:分层解耦
  • CommonJS 与 ES Modules 区别:
    • CommonJS:同步、动态加载模块,导出的是值拷贝;通过 module.exports 导出,require 导入
    • ES Modules:静态加载(编译阶段确定依赖关系),支持 Tree-Shaking,导出的是引用;通过 export / export default 导出,import 导入
  • Node.js 使用 ES Modules:扩展名为 .mjs,或在 package.json 指定 type 字段为 module
  • 循环依赖区别(低频考点)

3. Webpack

  • 是什么:静态模块打包构建工具
  • 解决的问题:解决浏览器兼容问题,以及性能优化问题
  • 核心概念:
    • entry:入口
    • output:输出
    • loader:文件转译
      • css 相关:style-loader、css-loader
      • js 相关:babel-loader
      • thread-loader:开启多线程
    • plugin:插件,处理整个构建流程
    • module:单文件模块
    • chunk:多个 module 构成,按照包更新频率进行分割
    • bundle:最终文件产物
  • 构建流程:
    1. 初始化阶段:读取配置,初始化 compiler 对象(管理配置、插件、生命周期);注册 plugin(plugin 通过 apply 函数传入 compiler 对象实现)
    2. 编译阶段:根据入口文件分析依赖图;遇到模块单文件使用 loader 进行转化,生成 AST;配合代码分割等优化;最终生成 chunk
    3. 输出阶段:根据输出配置,生成 bundle 文件
  • 相关问题:
    • Tree-Shaking 原理、适用场景
    • 编译期间怎么提速
    • 多线程优化属于哪个阶段
  • loader 与 plugin 区别:
    • loader:函数,针对单文件内容进行转换(如 markdown 转 html、babel-loader、ts-loader、css-loader)
    • plugin:解决整个文件系统级别的问题,loader 只能处理单文件;通过 tapable 监听生命周期钩子执行

4. Vite

  • 冷启动:相比于 webpack,直接利用原生浏览器 ES Module 解析能力,绕过编译打包,按需编译访问的文件
  • 预构建:提前预构建 node_modules,并行处理;通过 esbuild(Go 语言编写的打包工具)实现多线程打包,合并多个文件及入口
  • 预构建目的:1. CommonJS 转 ES 格式;2. 合并请求,减少请求数

5. 包管理工具

  • npm:兼容性好,但会扁平化依赖,存在重复下载、幽灵依赖问题(包提升到根目录)
  • yarn:支持并行下载、缓存机制
  • pnpm:树形依赖结构,无幽灵依赖、无重复包;通过符号链接/硬链接减少重复包加载

6. Monorepo

  • 多包管理方案:解决依赖治理、代码复用、团队协作问题;统一一个仓库,统一管理依赖和发布

7. Turbopack:了解即可

8. CI/CD

  • 持续集成和部署:代码提交 → 自动构建 → 自动测试 → 部署上线
  • Docker:保障环境一致性和隔离性,了解即可

9. 测试

  • 共用函数:Jest
  • 组件级别:React Testing Library
  • E2E:端到端测试,覆盖完整流程

九、JavaScript 基础核心

1. 数据类型

  • 共 8 种
    • 基础类型:Symbol、String、Boolean、BigInt、null、undefined、Number
    • 引用类型:Object
  • 基础类型与引用类型区别
  • 如何避免被修改:浅拷贝、深拷贝
    • 浅拷贝:只拷贝第一层,嵌套对象只复制地址,无法完全隔离
      • 实现方式:Object.assign、解构运算符、数组专用(slice、concat)
    • 深拷贝:递归处理,生成完全独立的副本
      • JSON.stringify 方案:无法处理循环引用、函数、异常值
  • 工程运用:React 中 immer 底层基于浅比较、纯函数思想,返回新的对象,简化不可变数据操作
  • 浅比较:处于性能平衡考虑,避免大对象深度对比
  • 栈与堆:
    • 基础数据类型存栈,引用类型存堆
    • 栈是值的拷贝,堆是值的引用
    • 基础类型不可变,引用类型可变
    • 栈存放基础数据类型原因:栈结构简单,空间有限,提升查询效率;堆存引用类型,结构复杂,内存支持动态变换,适配复杂类型

2. 类型判断

  • typeof:可判断基础数据类型,引用类型无法精细判断;typeof null 为 object(JS 早期设计缺陷:null 用全0字符表达,object 也用0标识,导致误判)
  • instanceof:无法精准判断所有引用类型,无法判断基础类型;通过原型链机制判断
  • Object.prototype.toString.call:最精确
  • Array.isArray:专门判断数组

3. 浮点数精度问题

  • 0.1 + 0.2 !== 0.3
  • 原因:IEEE 754 标准,计算机会进行二进制转换,小数点存在精度截断
  • 结构:1 位符号位、11 位指数位、52 位有效数字位
  • 最大安全整数:2^53 - 1;-1 是为了精度不溢出,53 位包含一个前导 1
  • BigInt:超出 2^53 - 1 的数值,可安全表示

4. Symbol

  • 用途:模拟私有变量,解决命名冲突,工程协作中常用
  • Symbol.iterator:迭代器,用于部署可迭代对象

5. 事件循环

  • 是什么:解决异步任务调度的事件管理机制
  • 背景:针对 JS 单线程特性,解决异步任务造成的阻塞现象
  • 构成:
    • 调用栈:压入执行同步任务
    • 宏任务:定时器、事件监听器、UI 渲染、MessageChannel;MessageChannel 用于 React 内部调度,替代 requestIdleCallback;由宿主环境(浏览器、Node)发起
    • 微任务:JS 引擎 API 发起;包括 Promise.then/catch/finally、MutationObserver、queueMicrotask、process.nextTick(Node 中优先级最高)
    • Web API
  • 执行顺序说明:
    • 先执行同步代码,再清空微任务队列,再执行一个宏任务,再清空微任务
    • requestAnimationFrame 执行时机:微任务之后、下一个宏任务之前执行
  • 浏览器与 Node 事件循环区别:
    • 浏览器:每次执行一个宏任务,就清空一次微任务队列
    • Node:微任务清空在每个阶段后;宏任务队列是批量执行,不是单个执行
    • 示例:两个 setTimeout 都进入 Timers 宏任务队列,执行顺序为:定时器 1 执行 → 定时器 2 执行 → 微任务 1 → 微任务 2
    • 底层差异:浏览器由浏览器内核驱动,Node 由底层 libuv 库驱动
    • Node 无 UI 渲染,存在最高优先级的 process.nextTick

6. 作用域与闭包

  • 作用域是什么:变量生效的范围和规则
  • 词法作用域:作用域由代码定义的位置决定,而非调用的位置
  • 分类:
    • 全局作用域
    • 局部作用域
      • 函数作用域
      • 块级作用域
  • React 中的函数作用域陷阱:需要用函数式更新、useEffect 来解决
  • 作用域链:链式嵌套结构,解决查找外部作用域变量的机制
  • 工程应用:webpack 作用域提升,避免嵌套作用域查询效率低下
  • 变量提升:早期 JS 的代码容错机制,提早预解析提升效率,但影响工程规范;后续引入 let、const 形成暂时性死区,不允许提前访问,要求先定义后访问
  • 闭包:
    • 定义:词法作用域下,引用外部局部作用域自由变量的函数,二者的组合就是闭包
    • 注意:单纯引用全局变量不是闭包;闭包的价值之一是延长局部作用域生命周期,全局变量本身不需要闭包
    • 应用场景:缓存、防抖节流、变量私有化、偏函数、模块化(立即执行函数)
    • 闭包带来的问题:引用的局部变量不会被销毁,造成内存泄漏;如定时器未清除
    • 解决方式:及时断开引用、使用 WeakMap 弱引用、组件卸载时及时清除定时器
  • WeakMap:
    • 键只能是对象
    • 不可被迭代,键值对随时可被垃圾回收
    • 弱引用特性

7. this 指向

  • 是什么:动态的上下文注入机制
  • 绑定方式:call、apply、bind(显式绑定)、隐式绑定
  • 绑定优先级:
    • new 绑定:优先级最高,其余绑定规则都会失效;this 始终指向实例对象
    • 显式绑定:call、apply、bind
    • 隐式绑定:谁调用,this 指向谁
    • 默认绑定:独立调用时默认指向 window
  • 箭头函数:
    • this 始终为外部词法作用域的 this
    • 没有原型对象
    • 无法作为构造函数
    • 无法使用 new 操作
    • 没有 arguments 对象,可用剩余参数替代
  • this 丢失场景:
    • 定时器:回调独立调用,默认指向 window
    • forEach、map:回调都是独立调用,默认指向 window;可通过传入 this 参数解决
    • 事件监听函数:普通函数指向目标 DOM 对象(内部自动绑定);箭头函数继承外层作用域 this
  • 继承场景特殊规则:super 调用后,父构造函数的 this 指向子类实例对象

8. 原型与原型链

  • 原型是什么:原型模式用于实现继承;从结构上就是对象,构造函数的 prototype 指向原型对象
  • 作用:能通过原型链查询,实现属性方法的复用
  • 继承实现方式:原型继承、组合继承、寄生继承、寄生组合继承、ES6 class
  • 弊端:原型污染(覆盖原型链上的属性方法)
  • 规避方式:规范与 ESLint 禁止覆盖原型;使用 Object.create(null)、Map
    • Map:键独立存储,不查询原型链
    • hasOwnProperty:检查自有属性
    • Object.create(null):创建无原型链的纯净对象,避免原型链干扰
  • 相关问题:如何判断一个纯对象?1. __proto__ 是否指向 null(Object.create(null));2. 隐式原型的 constructor 是否指向 Object 构造函数

9. 异步编程

  • 价值:解决非阻塞线程问题,突破单线程语言限制
  • 发展历程:回调地狱 → Promise → Generator → async/await
  • Promise:
    • 特性:一旦状态改变绝对不可逆
    • 三种状态:pending、fulfilled、rejected
    • 实例方法:then、catch、finally
    • 静态方法:all、race、allSettled、any、resolve、reject
    • 取消方式:加入标志位、AbortController
  • Generator 生成器
  • async/await:
    • 规则:async 函数如果返回普通值,会被 Promise.resolve 包裹;如果是 Promise 对象则直接返回
    • 原理:依赖 Promise 外加 Generator + next 自执行综合实现

10. ES6 特性

  • var、let、const 区别
  • Symbol / BigInt
  • Map、Set、WeakMap:哈希表结构,O(1) 查询操作;WeakMap 通过弱引用解决 Map 引发的内存泄漏问题
  • 解构、展开运算符:常用于简化取值操作
  • 箭头函数:简化函数写法,注意 this 指向问题

十、TypeScript

1. TS 是什么

  • JS 的超集,静态类型语言
  • 解决的问题:解决 JS 动态类型运行时才发现类型错误的问题(JS 报错排行第一就是类型相关错误)
  • 提升项目的易读性、健壮性
  • 本质:用 TS 实现了一个编译器

2. 编译原理

  1. parse 解析 TS:词法分析、语法分析
  2. 类型检测:检测类型是否规范,不规范则报错
  3. 代码生成:去除所有类型内容并进行转译,输出浏览器可识别的 JS

3. 常用类型

  • 基础 8 种数据类型
  • 元组:解决数组元素类型不同的场景
  • 枚举:
    • 字段更语义化、可扩展;数字枚举支持反向映射
    • enum 枚举:编译期会生成完整对象,可遍历、可反向映射
    • const enum:编译期不生成对象,运行时直接返回值,不可遍历
  • 联合类型:类型存在多种可能性
  • 交叉类型:实现类似类型继承的效果
  • any、unknown(类型安全的 any)、never(抛错时、绝对无返回值场景)、void(函数无返回值)
  • type 类型别名:可定义任意类型别名,提高可维护性;实现复用和语义化
  • type 与 interface 区别:
    • type 扩展用交叉类型,interface 用 extends
    • type 支持任意类型别名,interface 仅支持对象和函数
    • type 专注于任意类型别名,interface 专注于对象、继承
  • as 类型断言:
    • 本质:编译期指定具体类型
    • 用途:对 any、unknown 类型恢复类型判断;对联合类型收窄类型
  • 泛型:提升扩展性
    • 分类:函数泛型、类泛型、参数泛型、接口泛型
    • 泛型约束:通过 extends 对泛型进行类型约束、收窄
  • 逆变与协变:
    • 协变:子类型可以赋值给父类型
    • 逆变:父类型可以赋值给子类型

十一、React

1. React 是什么

  • 数据驱动视图的 UI 库(state/props 变化 → reconcile 协调 → 计算最小变化 → DOM 更新 → UI 变化)
  • 核心思想:函数式编程、严格单向数据流、声明式写法、JSX 描述 UI、组件化(实现解耦、复用)

2. Fiber

  • 是什么:
    • 数据结构层面:链表结构,包含组件信息、优先级、指针
    • 为什么用链表:通过指针指向,便于中断和恢复执行
  • 结构:
    • type:节点类型
    • memorizedState:当前状态
    • child:子节点指针
    • sibling:兄弟节点指针
    • return:父节点指针
    • alternate:指向 workInProgress 树
    • key:节点标识
  • 算法层面:协调算法,通过优先级调度、时间分片、双缓存树 diff 对比
  • 双缓存树:
    • 优势:保障 UI 一致性,无中间状态;支持可中断、可恢复
    • 通过 alternate 实现双缓存树互相指向、交替轮换
  • 时间分片:
    • 任务拆分为 5ms 一个单位
    • 判断当前帧有无空闲,超时则让出控制权,执行下一个 fiber 单元
    • 每次指向当前 fiber 单元,检测是否超时;超时后保存下一个工作单元,执行完毕后再返回
    • 配合宏任务 MessageChannel 模拟时间窗口调度
  • 工作循环:
    • 循环执行 fiber 任务(深度优先遍历 DFS)
    • 每次执行前判断当前帧是否有空闲:有则继续循环执行;没有则跳出执行循环并保存工作单元,下一次继续执行
  • 解决的问题:
    • 解决 React 15 及之前同步更新阻塞的问题(根源是 JS 是单线程语言)
    • 目标:实现可中断、可恢复的更新,支持并发特性(调度、时间分片、协调算法等)

3. 协调与提交

  • 协调阶段(Reconcile)
    • beginWork:处理当前 fiber 节点,根据 props 和 state 计算新的 workInProgress;执行 diff 对比,同层级打标签(增删改)
    • completeWork:根据更新后的 fiber 树,创建/更新 DOM 节点,不立即插入
    • 配合 Scheduler 实现任务调度、时间分片、协调 diff
  • 提交阶段(Commit)
    • 同步更新,不可中断
    • beforeMutation:调度 useEffect,DOM 操作前执行
    • mutation:根据协调阶段 diff 打的标签,执行 DOM 更新操作
    • layout:执行 useLayoutEffect,更新 ref
    • 职责:将副作用同步到 DOM 上,并先后触发 useLayoutEffect 和 useEffect

4. 优先级调度

  • 通过 Scheduler 调度
  • 通过 Lane 模型分配优先级
  • 遇到高优先级,会重新执行 render 逻辑,丢弃之前进行中的 workInProgress 构建
  • Lane 模型:基于位运算,高效;可同时存在多个优先级,便于复杂调度
  • Scheduler + Lane 模型 + 可中断的 render 共同实现并发更新
  • 为什么不用 requestIdleCallback:兼容性差,且无法精细化调度
  • 通过 MessageChannel 宏任务进行模拟:在下一次事件循环执行,不会阻塞浏览器渲染

5. Diff 算法

  • 是什么:协调对比算法,找出最小差异更新,保证最少 DOM 操作,减少回流
  • 三个策略:
    • 元素 key 对比:循环列表通过 key 对比
    • 组件层级对比:类型不同(如 div 变 span)直接删除重建
    • 树层级对比:同层节点不一致,所有子节点全部删除重建
  • 时间复杂度低
  • 分类:
    • 单节点对比:挨个对比,标记副作用;同时判断 key 和 type
    • 多节点对比:两次遍历,第一次找可复用节点,第二次处理移动;新节点遍历完、旧节点还有剩余则删除;新节点未完、旧节点无则创建
  • key 的作用:用于 diff 过程的节点复用
  • key 随机/不唯一的弊端:会导致复用错误、状态错误

6. Hooks

  • 是什么:函数式编程的体现,解决函数组件本身无状态的问题
  • 本质:代表函数式编程中的组合模式,常规场景优于继承,解决工程中的封装和扩展问题
  • 为什么不能在条件语句中使用:
    • Hooks 在编译期通过链表节点的 next 指针确定调用顺序
    • 更新时会按照定义的 hooks 调用顺序依次执行更新
    • 运行时如果顺序变换,会导致状态更新错误、渲染异常
  • useState 流程:
    • 创建 hook 链表,memorizedState 存储状态值
    • 初始化状态值
    • 维护更新队列,next 指向下一个 hook
    • set 方法:触发推入更新队列,批量执行
    • 渲染阶段:基于更新队列,按照链表顺序更新状态,返回新值和改值操作
  • useEffect:
    • beforeMutation 阶段调度 useEffect
    • 绘制后异步执行 useEffect 回调
    • 初始化创建 effect 对象,包含 deps、执行回调、清理函数、next 指针
    • 更新时从 memorizedState 读取旧依赖,和传入的新依赖做浅比较
    • 执行顺序:先立即执行清理函数,再执行内部回调
  • 自定义 Hook
  • useImperativeHandle 适用场景

7. 合成事件

  • 是什么:React 自己模拟浏览器事件机制,主要处理事件冒泡,将监听事件集中代理
  • 为什么做合成事件:
    • 屏蔽浏览器兼容差异
    • 可控性强,便于调度
    • 与 Fiber 融合,支持可中断处理
  • 原理:
    • 事件代理到根节点(React 17 及之后代理到 root 容器,16 及之前代理到 document)
    • 提升性能,降低内存占用;方便多个 React 版本共存,彼此隔离
  • 执行顺序:
    • 原生事件先执行,合成事件在 root 冒泡阶段才执行,时机更晚
    • 原生事件捕获、冒泡完毕后,再执行合成事件的冒泡
    • 原生事件的 e.stopPropagation 无法阻止合成事件
    • 阻止方式:1. 通过 e.nativeEvent 原生事件阻止冒泡;2. 设置事件捕获模式
    • 规范上不建议原生事件与合成事件混用

8. Redux

  • 是什么:全局状态管理库
  • 解决的问题:深层组件状态共享造成的重渲染难题
  • 核心原则:
    • 单一 store:易于持久化、统一管理
    • 纯函数修改:具备确定性、可测试
    • 数据不可变
    • 单向数据流
  • react-redux:
    • 作用:将状态和 UI 绑定,从而驱动页面更新
    • 原理:基于 createStore 创建数据源;定义 action 决定对数据的处理;reducer 接收 dispatch 发出的 action 并返回新的 state;组件订阅 state 的变化从而重新渲染
  • 中间件:
    • 定义:增强 dispatch 功能的函数
    • 执行时机:处于 dispatch 之后,到达 reducer 函数之前
    • 原理:洋葱圈模型,高阶函数实现

9. 组件生命周期

  • 挂载时:constructor → componentWillMount → componentDidMount
  • 更新时(props/状态更新触发):componentWillReceiveProps → shouldComponentUpdate → componentWillUpdate → render → componentDidUpdate
  • 卸载时:componentWillUnmount

10. JSX 本质

  • createElement 的语法糖
  • React 17 版本后 JSX 转换的修改

11. 版本差异

  • React 17 相比于 16 的改进
  • React 18 的改进

十二、浏览器渲染

1. 渲染进程与流程

  • 词法分析:拆分字符(UTF-8)为最小 token 单位
  • 语法分析:根据结构信息构建语法树
  • 构建 DOM 树
  • 构建 CSS 树(CSSOM):与 DOM 树并行处理,互不阻塞
    • 作用:计算可视元素样式,提供访问接口,生成 CSS 树
    • 不阻塞 DOM 树构建,但会阻塞后续渲染树构建
  • 渲染树(Render Tree):DOM 树和 CSS 树合成构建,会被 CSS 阻塞;只包含可视节点,display: none 的节点不包含
  • 布局(回流):重新计算元素几何位置
  • 绘制(重绘):重新绘制图像像素
  • 合成:合并多个图层,GPU 处理合成图像

2. JS 阻塞问题

  • DOM 和 CSS 构建遇到 JS 都会阻塞,因为 JS 可能操作 DOM 或 CSS,需要等待其执行完
  • CSS 放头部的原因:避免阻塞渲染树构建
  • defer 与 async 区别:
    • 共同点:都是异步加载,不阻塞 DOM 解析
    • defer:加载完毕推迟执行,DOM 解析完毕后执行,保证执行顺序,强调依赖顺序
    • async:加载完毕立刻执行,不保证顺序,适合无依赖的脚本

3. 回流与重绘

  • 回流
    • 定义:重新计算布局
    • 触发场景:元素几何属性、位置信息变化,操作 DOM
    • 如何减少回流:
      • 批量/离线操作 DOM
      • 虚拟滚动,减少 DOM 数量
      • 防抖/节流
      • 提升到合成层(跳过回流),如 transform、will-change
    • 结论:回流一定触发重绘,重绘不一定触发回流
  • 重绘
    • 定义:重新绘制图像像素
    • 触发场景:元素颜色、样式等非几何属性变化
    • 流程:从背景到元素逐节点绘制;光栅化转换为像素数据
  • 合成层
    • 独立的绘制层,由 GPU 处理
    • 触发方式:transform、opacity、will-change
    • 注意:合成层不宜过多
  • GPU 进程:负责 3D 绘制、硬件加速
  • 插件进程、网络进程

4. 多进程优势

  • 充分利用多核能力,提升效率
  • 分治思想:保障稳定安全,避免单进程崩溃导致整个浏览器崩溃

十三、HTTP

1. 定义

传输协议,用于数据请求和传输,处于应用层

2. HTTP 1.0 / 1.1 区别

  • 连接方式:1.0 是短链接、串行请求(一个请求一个响应);1.1 支持长连接,通过 Connection: keep-alive 可设置过期时间
  • 缓存:1.0 只有 expires 过期时间;1.1 支持 Cache-Control、Etag
  • 新增 host 头、状态码等
    • host:区分同一个 IP 地址下不同域名的请求
    • origin:跨域标识,包含协议、端口、域名
    • referer:请求来源,用于行为监控统计
  • 常见状态码:301、302、304、307
    • 307 等价于 302 的保障版,临时重定向,保持请求方法一致

3. HTTP 2.0

  • 多路复用:多个请求并发,复用一个 TCP 连接,应用层不阻塞
  • 二进制帧 + 流 ID 机制:服务端通过 ID 重组数据,不阻塞应用层
  • 请求头压缩:HPACK 算法,维护索引映射表,只传输索引,减少传输消耗

4. HTTP 3.0

十四、性能优化

1. 性能指标

  • TTFB(首个字节响应时间)
    • 优化方向:HTTP2、服务端缓存、CDN、默认开启 keep-alive
  • FP(首次绘制):首个任意内容绘制
  • FCP(首次内容绘制):首个文本、图片、canvas 等内容绘制
  • LCP(最大内容绘制) :视口内最大内容绘制时间,内容动态变化时值也动态变化
    • 统计对象:img、背景图、包含文本的块级元素
    • 优化方向:预加载、多级缓存、CDN、CSS 内联关键样式、JS 延迟加载(async)
  • FID(首次交互延迟)
    • 优化方向:Web Worker 开启辅助线程降低主线程压力;useTransition 提高用户操作优先级;分包、按需加载减少 JS 体积
  • TTI(完全可交互时间):技术指标,FID 更贴近实际用户感知
  • 测量工具:Lighthouse、Performance Timing、PerformanceObserver、web-vitals
  • 上报方式:集中通过 sendBeacon / fetch 兼容上报

2. 加载性能优化

  • 资源压缩
  • 预加载系列:
    • pre-dns:提前 DNS 解析
    • pre-connect:提前建立 TCP、TLS 连接
    • preload:预加载并立即执行,用于关键 CSS、字体资源
    • prefetch:空闲时执行,用于非首屏关键资源
  • CDN
  • HTTP 2.0 多路复用
  • Tree-Shaking
  • 按需加载

3. 渲染性能优化

  • 虚拟滚动
  • Web Worker 离线计算
  • requestIdleCallback 空闲执行
  • React.memo 等组件缓存
  • 减少直接操作 DOM 的回流行为
  • 防抖和节流

十五、前端监控

1. 行为监控

  • rrweb:监控回放用户行为,追踪完整链路
  • 采集粒度:页面级别、元素级别
  • 上报方式:sendBeacon、fetch、img(img 只有 get 方法,受浏览器参数限制)

2. 性能监控

  • performance.timing:记录各种性能指标时间
  • performanceObserver:检测性能指标及渲染性能,更全面
  • resource-timing:资源加载时间统计

3. 错误监控

  • JS 错误:监听 error 事件
  • Promise 错误:监听 unhandledrejection
  • 资源加载错误:通过 target 区分 window 与资源
  • 请求错误捕获等
  • sourceMap:源码映射压缩文件,用于定位错误位置;只在服务器上传一份,不暴露到前端

4. 白屏检测

  • 采样检测:检测是否有关键节点 DOM 元素
  • MutationObserver 检测 body 子节点变化次数

十六、系统设计

1. 组件库设计

  • 主题系统:Context + CSS 变量控制
  • 多语言
  • 按需加载:通过 babel-import-plugin 自动切换路径
  • 公共库:轻量化
  • 组件开发:TS 类型完善、规范接口、尽可能做受控组件、配套可用文档
  • 配套监控

2. 文件上传设计

  • 大文件切分:固定大小切分
  • 并发上传:按照切分后的模块进行并发限制上传
  • 续传:记录已上传成功的分片及对应索引

十七、CSS 补充

1. HTML 语义化

  • 优势:扩展性、可读性好,SEO 友好
  • 常用标签:header、title、nav、main 等

2. H5 新 API

  • localStorage、WebSocket、Web Worker、Canvas、SVG

3. 盒模型

  • 标准盒模型(content-box):宽高不包含 border 和 padding
  • IE 盒模型(border-box):宽高包含 border 和 padding,更符合直觉,width 就是实际宽度
  • 通过 box-sizing 设置

4. BFC(块级格式化上下文)

  • 定义:独立的渲染区域,内部的元素布局不影响外部布局
  • 解决的问题:
    • 清除浮动:父元素触发 BFC 后,内部浮动元素会被计算高度
    • margin 重叠:包裹子元素避免 margin 重叠
    • 自适应布局:浮动元素 + 右侧 BFC 元素实现自适应宽度
  • 触发方式:
    • float 不为 none
    • overflow: hidden(元素不溢出,触发 BFC)
    • display: flex / flow-root(flow-root 专门用于生成 BFC)
  • 验证:通过 computed 查看 block 标识,判断是否清除浮动、margin 是否重叠

5. 清除浮动

  • 伪元素清除浮动:.clearFix::after { content: ''; display: block; clear: both; }
  • 原理:通过 after 伪元素添加一个空内容块级元素,设置 clear: both 实现清除
  • 触发 BFC 也可清除浮动

6. Flex 布局

  • 容器属性(父元素):
    • flex-direction:row(横向)、column(竖直)
    • flex-wrap:wrap、nowrap
    • justify-content:center、space-between、space-around、flex-start、flex-end
    • align-items:center、flex-start、flex-end
  • 元素属性:
    • flex-grow:0 / 1,放大比例
    • flex-shrink:0 / 1,缩小比例
    • flex-basis:初始大小
      • 0%:完全由 grow 决定大小
      • auto:初始由自身内容决定

十八、缓存

1. 强缓存与协商缓存

  • 强缓存:通过 Cache-Control 的 max-age 控制
  • 协商缓存:通过 Etag、Last-Modified 验证
  • 验证字段:
    • If-Modified-Since:对应 Last-Modified
    • If-None-Match:对应 Etag

2. 缓存整体流程

  • 为什么要有缓存:避免每次请求都让服务器重新发送资源,提升访问效率
  • 可缓存资源:静态资源(img、css、js)
  • 不建议缓存:HTML(结构可能随需求变更)
  • 强缓存流程:
    1. 首次浏览器向服务器发起 HTTP 请求
    2. 服务器返回资源,响应头包含 Cache-Control: max-age(资源失效时间)
    3. 浏览器将资源与缓存标识(Last-Modified、Etag)存放在本地缓存
    4. 第二次请求资源时,先访问本地资源,同时判断资源是否过期(依据 Cache-Control max-age / expires)
    5. 未过期:本地缓存直接返回资源
    6. 过期:进入协商缓存流程
  • 协商缓存流程:
    1. 携带之前服务器返回的缓存标识(Etag / Last-Modified)发送请求给服务器
    2. 服务器对比自己最新的标识与客户端发来的标识
    3. 一致:返回 304,告知资源未更新,继续使用本地缓存
    4. 不一致:返回 200 和新的资源
  • 相关属性说明:
    • expires:HTTP 1.0 字段,绝对服务器时间,与客户端时间有误差
    • Cache-Control:
      • max-age:以客户端时间做差值计算
      • no-cache:不命中强缓存,直接走协商缓存
      • no-store:没有任何缓存,既不走强缓存也不走协商缓存,每次都请求最新资源
      • public:可以被代理服务器缓存
      • private:不能被代理服务器缓存
    • Etag / Last-Modify:
      • Etag:服务器依据内容生成唯一标识字符串,会消耗服务器资源;精度更高,防止误判
      • Last-Modify:资源最新的修改时间
    • 适用场景:Etag 适合动态接口做精准校验;静态资源用 Last-Modified 更高效

十九、HTTPS

1. 是什么

基于 HTTP 协议,下层依赖 TLS 握手保证传输安全

  • 解决 HTTP 明文传输的弊端
  • 端口号 443(HTTP 为 80)
  • 核心特性:加密、验签、摘要,共同保证安全

2. 混合加密机制

  • 对称加密:AES 算法,安全中等、性能好,适用于对话传输阶段;平衡性能与安全
  • 非对称加密:ECDH 算法,安全性高、性能差,适用于密钥交换阶段;保证传递的密钥未被更改

3. TLS 握手流程

  • HTTPS 1.2:2 个 RTT

    1. 客户端:发送版本、密码套件、随机数
    2. 服务端:返回版本、密码套件、随机数、证书
    3. 客户端:验证证书链,生成预主密钥
    4. 服务端:接收后,综合三个密钥生成主密钥,开始加密通话
    • 验签原理:CA 私钥加密证书摘要,客户端用公钥解密摘要,再通过摘要算法对比证书内容是否改变
  • HTTPS 1.3:1 个 RTT 优化,支持 0-RTT 缓存优化

二十、TCP / UDP

1. TCP 是什么

传输控制协议,解决端到端的、面向连接的、字节流的可靠传输;基于传输层

2. 三次握手

  1. 客户端向 TCP 发送连接请求:SYN=1,发送 seq
  2. 服务端接收后:返回 seq 和基于上一个 seq 的确认 ACK
  3. 客户端:再次发送 ACK,开始通信
  • 为什么不是两次:两次无法进行双向确认,会被旧链接干扰
  • 为什么是三次:保障双向确认,避免旧链接请求干扰

3. 四次挥手

  1. 发送方:发送 FIN 终止报文和 seq
  2. 接收方:返回 ACK 确认
  3. 接收方:待剩余数据发送完毕,发送 FIN 终止报文和 seq
  4. 发送方:返回 ACK 确认,等待 2MSL 后进入 CLOSED 状态
  • 等待 2MSL 原因:防止服务端未收到最后一个 ACK,重发 FIN 时客户端可重发 ACK;保证两个报文的最大生命周期内都能处理
  • 为什么是四次:全双工通信需要双向确认;服务端结束前通常还有剩余数据要发送

4. TCP 特性

  • 面向连接
  • 可靠性保障
  • 拥塞控制:慢开始(指数增长窗口)、拥塞避免(线性增长)、快重传、快恢复
  • 流量控制:防止发送方数据过快,确保服务端可处理;通过滑动窗口机制保障
  • 头部开销:20 字节
  • 适用场景:HTTP、HTTPS、FTP 文件传输等所有需要准确完整的场景

5. TCP 安全与问题

  • SYN 泛洪攻击:只发请求不确认;防范:限制同 IP 地址请求速度
  • 粘包和拆包:
    • 粘包:TCP 为了优化会合并小数据包,导致数据粘连
    • 拆包:服务端接收能力有限,超过限制会拆包
    • 解决:固定包大小、包体加长度标识

6. UDP

  • 无连接、无可靠机制保障
  • 头部开销:8 字节
  • 适用场景:语音、直播、DNS

二十一、架构设计与编码规范

1. MVC

  • 分层:
    • Model 模型层:单独处理业务逻辑
    • View 视图层:UI 组件仅承接数据展示,不涉及业务及数据处理
    • Controller 控制层:涉及数据获取、数据格式化相关
  • 价值:使项目层级结构分明,易于维护

2. 虚拟滚动

  • 适用场景:万级数据列表渲染
  • 目的:避免同时渲染过多 DOM 造成卡顿
  • 原理(固定高度场景):
    • 确定整个可视区域高度
    • 将区域划分为上缓冲区、可视区域、下缓冲区
    • 记录用户滚动距离、可视区域与缓冲区上下边界,动态计算各元素距顶部距离,实现动态加载
  • 不定高度场景的实现思路

3. Node 相关

  • Node 处理了哪些场景
  • 遇到大文件怎么处理读取
相关推荐
陈随易2 小时前
编程语言级别的Skill市场,AI Agent 的未来形态
前端·后端·程序员
SoaringHeart3 小时前
Flutter进阶:基于 EasyRefresh 的下拉刷新封装 n_easy_refresh_mixin.dart
前端·flutter
IT_陈寒5 小时前
Vite的热更新突然不香了,排查三小时差点砸键盘
前端·人工智能·后端
子兮曰5 小时前
Agency-Agents 深度解析:400+ AI 专家的"梦之队"如何重塑开发工作流
前端·后端·vibecoding
竹林8186 小时前
用 The Graph 查询链上数据实战:从手搓 RPC 到 Subgraph,我的 NFT 项目数据加载快了 10 倍
前端·javascript
妙码生花6 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十九):点选验证码代码逐行目检
前端·后端·go
Awu12277 小时前
⚡从零开发 Agent CLI(五)实现一个可治理、可扩展的工具系统
前端·人工智能·claude
咪库咪库咪8 小时前
Vue3-生命周期
前端
莪_幻尘8 小时前
你的 AI Skill 越多越蠢?Token 上下文爆炸的求生指南
前端·ai编程