浏览器安全
一、XSS 攻击(跨站脚本攻击)
1. 定义
代码注入攻击 ,攻击者注入恶意脚本 到网站,浏览器无法区分可信脚本,导致恶意代码执行,进而盗取 cookie、篡改页面、劫持流量等。
2. 攻击类型(核心区别:恶意脚本存储 / 执行位置)
- 存储型 xss :恶意脚本存入目标服务器 (如评论、私信、用户资料),用户请求时从服务器返回执行(危害最大,影响所有访问该页面的用户);
- 反射型 xss :恶意脚本藏在 URL 中,服务器拼接后返回执行(需诱导用户点击恶意 URL,仅影响单个用户);
- DOM 型 xss :通过修改页面Dom结构注入脚本(仅前端漏洞,与服务端无关,不经过服务器处理)。
3. 防御措施(核心:过滤输入、控制输出)
- 输入输出转义 :对用户输入的特殊字符(如
<>'")转义,避免拼接为 HTML/JS 执行; - 启用 CSP(白名单) :通过 HTTP 头(
Content-Security-Policy)或 meta 标签指定可信资源白名单,阻止恶意脚本加载 / 执行; - 敏感 Cookie 设为 HttpOnly:禁止 JS 读取 cookie,从根源防止 cookie 被盗;
二、CSRF 攻击(跨站请求伪造)
1. 定义
攻击者诱导用户进入第三方网站,利用用户在目标网站的登录状态(cookie 同源自动携带),冒充用户发起跨站请求,执行非预期操作(如转账、改密码、发评论)。
2. 防御措施(核心:验证请求合法性)
- 验证 CSRF Token(核心方案):服务器返回随机 Token(存入页面 /cookie),请求时需携带 Token 验证,攻击者无法获取 Token 则无法伪造请求;
- 同源检测 :通过
Origin/Referer头判断请求来源,仅允许可信域名的请求; - 敏感操作加二次验证(如验证码、密码确认)。
三、中间人攻击
1. 定义
攻击者拦截客户端与服务器的通信,伪造双方身份,使双方误以为直接对话,核心目的是窃取 / 篡改传输数据。
2. 防御措施
- 全站 HTTPS(核心):加密传输链路,防止数据被拦截篡改;
- 验证服务器证书:拒绝接受伪造的 SSL 证书,避免信任恶意中间人。
四、其他前端安全问题
1. 常见风险
- iframe 滥用 :第三方 iframe 可能执行恶意脚本,需设置
sandbox属性限制权限(如禁止脚本、禁止跨域); - 恶意第三方库 :引入未审计的依赖可能携带恶意代码,需使用官方源、定期审计依赖(如
npm audit); - 网络劫持 :分 DNS 劫持 (篡改域名解析,输⼊京东被强制跳转到淘宝这就属于dns劫持)和 HTTP 劫持(明文插入广告 / 恶意代码,访问⾕歌但是⼀直有贪玩蓝⽉的⼴告)。
2. 网络劫持防御
- 全站 HTTPS(最有效):加密 HTTP 传输,运营商无法获取明文,无法篡改响应;
- 避免使用明文 HTTP 协议。
核心总结
- 前端安全核心原则:过滤输入、验证请求、加密传输;
- XSS 防御关键:转义 + CSP + HttpOnly Cookie;
- CSRF 防御关键:CSRF Token + SameSite Cookie;
- 数据传输安全关键:全站 HTTPS。
进程与线程
一、进程与线程核心概念
- 本质:均是 CPU 工作时间片的描述,用于衡量任务执行的时间维度。
- 核心定义(面试必记):
- 进程 :资源分配的最小单位,是程序的运行实例(操作系统为其分配内存,存放代码、数据和主线程);
- 线程 :CPU 调度的最小单位,是进程内的执行单元,一个进程可包含多个线程,共享进程资源。
- 进程与线程的核心关系:
- ① 任一线程出错 → 整个进程崩溃;
- ② 线程共享进程内数据,进程间资源 完全隔离;
- ③ 进程退出时,操作系统回收所有资源(包括线程泄漏的内存);
- ④ 进程间通信需借助专门的 IPC(进程间通信)机制。
二、Chrome 浏览器多进程架构(面试高频)
- 核心进程(打开 1 个网页最少需 4 个):
- 浏览器主进程:核心职责:界面显示、用户交互、子进程管理、存储;
- 渲染进程 :核心职责:解析 HTML/CSS/JS,构建 DOM/CSSOM/ 渲染树,运行 Blink 排版引擎和 V8 引擎;默认 1 个 Tab1 个进程,沙箱模式运行(安全隔离);
- GPU 进程:负责 UI / 网页绘制(3D CSS、页面渲染);
- 网络进程:负责资源加载(原属浏览器进程,后独立);
- 插件进程:隔离插件运行(避免插件崩溃影响浏览器)。
- 多进程优势与缺点:
- 优势:稳定性、流畅性、安全性提升(进程隔离,单个 Tab 崩溃不影响整体);
- 缺点:资源占用高(重复加载公共结构如 V8 引擎)、架构复杂。
三、进程与线程的核心区别(必背)
| 维度 | 进程 | 线程 |
|---|---|---|
| 资源分配 | 资源分配最小单位(有独立内存 / 资源) | 无独立资源,共享进程资源 |
| 调度 | 调度开销大(需保存整个进程环境) | CPU 调度最小单位,调度开销小 |
| 通信 | 需借助 IPC 机制(如管道、Socket) | 直接共享进程数据,通信简单 |
| 独立性 | 独立运行,进程崩溃不影响其他进程 | 依赖进程,线程崩溃导致整个进程崩溃 |
| 系统开销 | 创建 / 销毁 / 切换开销大 | 创建 / 销毁 / 切换开销小 |
四、浏览器渲染进程的 5 类核心线程(高频)
- GUI 渲染线程 :
- 核心职责:解析 HTML/CSS → 构建 DOM 树 / CSSOM 树 / 渲染树 → 绘制页面;处理重绘 / 回流;
- 关键:与 JS 引擎线程互斥(JS 执行时 GUI 挂起,导致页面卡顿)。
- JS 引擎线程(V8 引擎) :
- 核心职责:解析执行 JS 代码,单线程运行(1 个 Tab 仅 1 个);
- 关键:阻塞 GUI 渲染(JS 执行过长 → 页面卡顿)。
- 事件触发线程 :
- 核心职责:管理事件循环,将异步事件(点击、AJAX 回调)加入任务队列,等待 JS 引擎处理。
- 定时器触发线程 :
- 核心职责:独立计时(避免 JS 单线程阻塞影响精度),计时结束后将任务加入队列;
- 关键:最小延迟 4ms(W3C 标准),定时器任务 不一定准时执行(需等 JS 引擎空闲)。
- 异步 HTTP 请求线程 :
- 核心职责:独立发起网络请求,状态变更后将回调加入任务队列。
五、浏览器多标签页通信(4 种核心方式)
核心逻辑:中介者模式(标签页无法直接通信,需通过中介转发)
- WebSocket:借助服务器作为中介,实现实时通信;
- ShareWorker:共享独立线程,标签页通过该线程交换数据;
- localStorage :监听
storage事件,一个标签页修改数据,其他标签页通过事件获取; - postMessage:获取目标标签页引用后,直接发送数据(需指定目标源,避免安全风险)。
六、Service Worker(面试高频)
- 核心定义:运行在浏览器后台的 独立线程 (无 DOM 访问权限),核心用于实现 离线缓存、请求拦截;
- 必要条件:必须使用 HTTPS 协议(保障请求拦截安全);
- 实现缓存的 3 个步骤(面试必记):
- ① 注册:通过
navigator.serviceWorker.register('sw.js')注册; - ② 安装(install 事件):打开缓存空间,缓存静态资源(如 HTML/JS/CSS);
- ③ 拦截请求(fetch 事件):优先返回缓存资源,无缓存则请求服务器。
- ① 注册:通过
浏览器缓存
一、核心目的
减少网络请求、加快页面加载速度、减轻服务器负担,核心针对静态资源(JS/CSS/ 图片 / 字体等),减少多余网络传输。
二、缓存分类:强缓存 + 协商缓存(优先级:强缓存 > 协商缓存)
(一)强缓存(直接用本地缓存,不发请求)
- 定义:资源未过期时,浏览器直接从本地磁盘 / 内存读取,无需向服务器发起请求。
- 实现方式(HTTP 响应头):
- Cache-Control (HTTP 1.1,优先级更高):支持多指令,精准控制缓存:
max-age=xxx:缓存有效期(秒),核心指令;public:允许浏览器、CDN 等代理缓存;private:仅允许浏览器缓存(含用户信息的资源,避免 CDN 缓存);no-cache:跳过强缓存,直接走协商缓存(不是不缓存);no-store:完全禁止缓存,每次必发请求;s-maxage=xxx:仅作用于代理缓存(CDN),优先级高于max-age。
- Expires (HTTP 1.0):绝对过期时间(如
Wed, 20 Jul 2024 12:00:00 GMT),缺点是依赖客户端时间,易因时间不一致失效。
- Cache-Control (HTTP 1.1,优先级更高):支持多指令,精准控制缓存:
- 关键区别 :
no-cache:有协商缓存,需服务器验证资源是否更新;no-store:无任何缓存,每次都从服务器下载新资源。
(二)协商缓存(发请求问服务器,资源未变则用缓存)
-
触发条件:
- 强缓存过期(
max-age超时 /Expires过期); - 资源配置了
Cache-Control: no-cache; - 浏览器 F5 刷新(跳过强缓存)。
- 强缓存过期(
-
实现方式(请求头 + 响应头配合):
响应头(服务器返回) 请求头(浏览器携带) 核心逻辑 缺点 Last-Modified If-Modified-Since 基于文件最后修改时间判断 精度仅秒级,1 秒内多次修改无法识别 Etag If-None-Match 基于文件内容哈希生成唯一标识 计算哈希有轻微性能开销 -
优先级:Etag > Last-Modified(服务器优先用 Etag 判断,弥补 Last-Modified 精度缺陷)。
-
触发结果:
- 资源未变:服务器返回
304 Not Modified,浏览器用本地缓存(不返回资源主体); - 资源已变:服务器返回
200+ 新资源,更新本地缓存。
- 资源未变:服务器返回
1. Last-Modified(响应头) + If-Modified-Since(请求头)
| 字段 | 类型 | 核心含义 |
|---|---|---|
| Last-Modified | 响应头 | 服务器返回,记录「资源最后一次修改的时间」(精确到秒级) |
| If-Modified-Since | 请求头 | 浏览器下次请求时携带,值为上一次服务器返回的 Last-Modified 值 |
作用流程 :服务器接收请求后,对比If-Modified-Since与资源当前最后修改时间:
- 一致(资源未改):返回
304 Not Modified,浏览器用本地缓存(不返回资源主体); - 不一致(资源已改):返回
200+ 新资源 + 新的 Last-Modified,更新本地缓存。
缺点:精度仅秒级,1 秒内多次修改文件无法识别;文件内容未变但修改时间变(如重新保存),会误判为资源更新。
2. Etag(响应头) + If-None-Match(请求头)
| 字段 | 类型 | 核心含义 |
|---|---|---|
| Etag | 响应头 | 服务器返回,基于「资源内容哈希生成的唯一标识」(内容变则 Etag 值必变) |
| If-None-Match | 请求头 | 浏览器下次请求时携带,值为上一次服务器返回的 Etag 值 |
作用流程 :服务器接收请求后,对比If-None-Match与资源当前 Etag 值:
- 一致(资源未改):返回
304,浏览器用本地缓存; - 不一致(资源已改):返回
200+ 新资源 + 新的 Etag,更新本地缓存。
核心优势 :精度远高于 Last-Modified,能精准识别内容变化;优先级高于 Last-Modified (服务器优先用 Etag 判断);缺点:服务器生成哈希有轻微性能开销;分布式服务器部署时需保证 Etag 一致性(否则易误判)。
三、完整缓存流程
- 首次请求:服务器返回资源 + 缓存头(
Cache-Control/Etag/Last-Modified等),浏览器缓存资源和响应头; - 再次请求:
- 第一步:检查强缓存 → 未过期 → 直接用本地缓存(控制台显示
200 from disk/memory cache); - 第二步:强缓存失效 → 触发协商缓存 → 浏览器发送带
If-Modified-Since/If-None-Match的请求; - 第三步:服务器验证资源 → 未更新(304)→ 用本地缓存;已更新(200)→ 下载新资源并更新缓存。
- 第一步:检查强缓存 → 未过期 → 直接用本地缓存(控制台显示
四、不同刷新方式的缓存行为(高频)
| 操作方式 | 核心逻辑 | 返回状态可能 |
|---|---|---|
| 地址栏回车 / 页面跳转 | 正常走缓存流程(先强缓存 → 再协商缓存) | 200 / 304 |
| 点击刷新按钮 / F5 | 跳过强缓存,直接走协商缓存(携带If-Modified-Since/If-None-Match) |
200 / 304 |
| Ctrl+F5(强制刷新) | 完全禁用缓存,不携带协商缓存请求头,直接请求服务器获取最新资源 | 200 |
五、关键细节与实战应用(加分)
- 缓存更新策略:给资源加版本号 (如
app.js?v=2.0)或哈希值 (如app.123abc.js),资源更新时修改标识,强制浏览器重新下载; - 静态资源配置建议:
- 长期缓存:
Cache-Control: public, max-age=31536000(缓存 1 年)+ 版本号 / 哈希; - 敏感资源(含用户信息):
Cache-Control: private, no-cache; - 禁止缓存:
Cache-Control: no-store(如动态接口返回的 HTML);
- 长期缓存:
- CDN 缓存配合:
Cache-Control: public, s-maxage=86400, max-age=3600(CDN 缓存 1 天,浏览器缓存 1 小时); - 常见误区:
max-age=3600不是绝对命中强缓存:F5 刷新、清除缓存会失效;- 跨域资源可缓存:需服务器配置
Access-Control-Allow-Origin,同时返回缓存头。
核心总结(面试必记)
- 缓存核心:强缓存省请求,协商缓存保新鲜;
- 关键头:强缓存看
Cache-Control/Expires,协商缓存看Etag/Last-Modified; - 刷新区别:F5 走协商缓存,Ctrl+F5 禁用缓存,地址栏回车走完整流程;
- 实战核心:静态资源长期缓存 + 版本号,敏感资源禁用强缓存,跨域资源需配置 CORS + 缓存头。
浏览器组成
一、浏览器核心定义
浏览器的核心功能是 请求并呈现 web 资源(HTML、CSS、JS、图片、PDF 等),通过 URI 指定资源位置,遵循 W3C 制定的 HTML/CSS 规范,但不同浏览器厂商的扩展可能导致兼容性问题。
二、浏览器整体结构
浏览器分为 shell(外壳) 和 内核(核心) 两部分:
- shell(外壳):用户可见的交互界面,如地址栏、前进 / 后退按钮、书签菜单、设置面板等,负责调用内核实现功能;
- 内核(核心) :浏览器的核心能力载体,早期包含渲染引擎和 JS 引擎,现在内核多特指 渲染引擎(JS 引擎已独立,如 V8)。
内核的组成
- 渲染引擎:核心职责是解析 HTML/CSS,构建 DOM 树、CSSOM 树、渲染树,最终将内容绘制到浏览器窗口;支持 HTML/XML/ 图片等格式,可通过插件扩展(如 PDF 阅读器);
- JS 引擎:独立解析和执行 JavaScript 代码,实现网页动态效果(如 V8 引擎、SpiderMonkey)。
三、浏览器的主要组成部分(7 大模块)
- 用户界面:地址栏、书签、前进 / 后退按钮等(除网页内容外的所有交互区域);
- 浏览器引擎:用户界面与渲染引擎的 "桥梁",传递操作指令(如点击链接→通知渲染引擎请求资源);
- 呈现引擎(渲染引擎):核心模块,解析 HTML/CSS 并绘制页面;
- 网络模块:处理 HTTP/HTTPS 请求、WebSocket 等网络通信,提供跨平台统一接口;
- 用户界面后端:绘制基础组件(按钮、输入框),适配不同操作系统(Windows/macOS);
- JavaScript 解释器:解析执行 JS 代码(如 V8 引擎),实现动态交互;
- 数据存储:持久化存储数据,如 Cookie、LocalStorage、SessionStorage、IndexedDB(HTML5 新增)。
关键特性
- Chrome 浏览器的特殊设计:每个标签页对应一个独立的渲染引擎实例(进程),实现进程隔离,单个标签页崩溃不影响整体浏览器运行。
浏览器渲染原理
一、核心渲染流程
- 解析 HTML → 构建 DOM 树:解析 HTML 标签,生成 DOM 节点树(含元素 / 属性 / 文本节点);
- 解析 CSS → 生成 CSSOM 树:解析内联 / 外部 CSS,生成样式规则树(记录每个元素的样式);
- 构建渲染树 :结合 DOM 树和 CSSOM 树,筛选可见节点(如
display: none节点不加入),生成渲染对象(含尺寸、颜色等样式信息); - 布局(回流) :计算渲染树节点的精确位置和大小,确定元素在页面中的布局;
- 绘制 :遍历渲染树,调用
paint方法将节点内容绘制到屏幕(使用 UI 组件渲染像素)。
关键特性 :渲染是渐进式的,解析一部分内容就渲染一部分,无需等待所有资源下载完成(提升用户体验)。

二、JS/CSS 对渲染的阻塞机制
1. JavaScript 的阻塞作用
- 核心:阻塞 DOM 解析 (HTML 解析器遇到
<script>会暂停解析,移交控制权给 JS 引擎,执行完再恢复); - 间接阻塞 CSSOM:JS 可能读取 CSS 样式,若 CSSOM 未构建完成,JS 会等待 CSSOM 就绪,进而阻塞 DOM 解析;
- 解决方案(异步加载 JS):
async:异步下载 JS,下载完成后立即执行(不保证执行顺序,适合无依赖脚本);defer:异步下载 JS,等待 DOM 解析完成后顺序执行(保证顺序,适合依赖 DOM 的脚本);- 推荐实践:
<script>放<body>底部,或用defer/async异步加载。
2. CSS 的阻塞作用
- 核心:阻塞渲染(需等待 CSSOM 构建完成,才能结合 DOM 树生成渲染树,否则无法渲染页面);
- 不阻塞 DOM 解析,但阻塞 JS 执行(如上述);
- 加载方式对比(面试高频):
link:并行下载 CSS,不阻塞 DOM 解析(推荐);@import:阻塞 DOM 解析和渲染,需等待 CSS 下载完成才继续(不推荐);- 内联
style:直接渲染,无阻塞(适合少量 CSS)。
三、渲染优化核心策略
1. 针对 JS 优化
- 优先异步加载:
defer/async替代同步<script>; - 避免首屏加载非必要 JS:将非核心 JS 延迟加载(如滚动加载、按需加载);
- 减少 JS 执行时间:压缩代码、拆分大脚本、避免长任务阻塞线程。
2. 针对 CSS 优化
- 用
link引入外部 CSS(替代@import); - 关键 CSS 内联(首屏必要样式写在
<style>标签,减少网络请求); - 简化 CSS 选择器:选择器从左到右解析,减少层级(如
.box .item→.box-item)。
3. 针对 DOM/CSSOM 优化
- 减少 HTML/CSS 层级:避免过深嵌套(降低解析和渲染树构建开销);
- 使用语义化标签(如
<header><section>):减少浏览器特殊处理,提升解析效率; - 避免无效 DOM 节点:删除冗余标签、空节点。
四、回流与重绘优化(重点)
1. 核心定义
- 回流(重排):布局阶段的重新计算(元素位置 / 大小改变触发,开销大);
- 重绘:绘制阶段的重新渲染(仅样式改变不影响布局,如
color/background,开销小); - 关系:回流必然触发重绘,重绘不一定触发回流。
2. 优化方案
- 脱离文档流:用
absolute/fixed定位(元素变化不影响其他节点); - 批量 DOM 操作:
- 用
documentFragment暂存 DOM 操作,最后一次性插入文档; - 先设
display: none(操作期间不触发回流),完成后恢复显示;
- 用
- 批量读写 DOM:将多个读操作(如
offsetWidth)和写操作分开执行(利用浏览器渲染队列批处理,减少回流次数); - 避免表格布局:
table小改动会触发全表回流; - 用 CSS 类批量修改样式(替代多次
style属性操作)。
五、关键概念解析
1. 文档预解析
- 定义:Webkit/Firefox 的优化机制,JS 执行时,另一个线程并行解析剩余 HTML,预加载外部资源(JS/CSS/ 图片);
- 特点:不改变 DOM 树,仅预加载资源,提升并行加载效率。
2. 关键渲染路径优化
- 核心目标:尽快完成首次渲染,需减小三个变量:
- 关键资源数量(阻止首次渲染的资源,如 HTML、核心 CSS、同步 JS);
- 关键路径长度(资源依赖关系导致的下载往返次数);
- 关键字节数(关键资源的总大小);
- 优化步骤:分析关键资源 → 减少关键资源数(异步 / 删除)→ 压缩字节数 → 优化加载顺序。
3. 什么情况会阻塞渲染?
- 直接阻塞:HTML 解析(构建 DOM)、CSS 解析(构建 CSSOM);
- 间接阻塞:未异步的 JS(阻塞 DOM 解析,进而阻塞渲染);
- 不阻塞:异步 JS(
defer/async)、图片(下载时不阻塞 DOM/CSS 解析,仅影响自身绘制)。
核心总结
- 渲染核心:DOM 树 + CSSOM 树 → 渲染树 → 布局 → 绘制;
- 阻塞关键:同步 JS 阻塞 DOM 解析,CSS 阻塞渲染和 JS 执行;
- 优化核心:减少阻塞资源、简化 DOM/CSS 层级、批量操作 DOM、避免不必要的回流重绘;
- 高频考点:
defer/async区别、link与@import区别、回流重绘优化、关键渲染路径。
浏览器本地存储
一、核心存储方式
1. Cookie(传统存储)
- 核心:服务端创建、客户端存储,每次 HTTP 请求自动携带 ,大小限制4KB;
- 核心特性:
- ✅ 跨子域共享(配置 Domain 字段),受同源策略约束;
- ✅ 可设置过期时间(Expires/Max-Age),默认会话级(浏览器关闭失效);
- ✅ 安全增强:
Secure(仅 HTTPS 传输)、HttpOnly(禁止 JS 读取,防 XSS); - 核心字段(面试必记):
- 使用场景:存储登录态(sessionId)、统计页面点击次数。
2. LocalStorage(HTML5 持久存储)
- 核心:客户端存储,不随 HTTP 请求携带 ,大小5MB ,持久化(手动清理才失效);
- 核心特性:同源限制(端口 / 协议 / 域名一致)、IE8 + 支持、隐私模式不可读;
- 常用 API:
setItem/getItem/removeItem/clear/key; - 使用场景:网站换肤配置、长期用户浏览记录、静态个人信息存储。
3. SessionStorage(HTML5 会话存储)
- 核心:客户端存储,不随 HTTP 请求携带 ,大小5MB ,会话级(窗口 / 标签页关闭失效);
- 核心特性:同源 + 同窗口限制(仅同一浏览器同窗口共享),API 与 LocalStorage 一致;
- 使用场景:游客登录信息、临时浏览记录、表单临时数据。
二、三者核心区别
| 维度 | Cookie | LocalStorage | SessionStorage |
|---|---|---|---|
| 存储大小 | 4KB | 5MB | 5MB |
| 请求携带 | 每次 HTTP 自动携带 | 不携带 | 不携带 |
| 有效期 | 可设过期 / 默认会话 | 持久化(手动清理) | 窗口关闭失效 |
| 共享范围 | 同源 + 跨子域(Domain) | 同源页面共享 | 同源 + 同窗口共享 |
| 核心用途 | 服务端交互(登录态) | 本地持久存储 | 本地临时存储 |
三、其他前端存储方式
1. Web SQL(已废弃)
- 关系型数据库(类 SQLite),主流浏览器(除 Firefox)支持,操作繁琐(需 JS 转 SQL),W3C 已废弃,面试仅作了解。
2. IndexedDB(HTML5 本地数据库)
- 核心:NoSQL 数据库,适配大量数据存储(弥补 LocalStorage 容量不足);
- 核心特性(面试高频):✅ 键值对存储,支持二进制数据(ArrayBuffer/Blob);✅ 异步操作(不阻塞浏览器)、支持事务(操作原子性,失败回滚);✅ 同源限制,存储空间大(≥250MB,无上限);
- 使用场景:离线应用数据存储、大量本地缓存(如离线报表)。
四、Web Storage(Local/Session)vs Cookie
- 容量:Web Storage(5MB)远大于 Cookie(4KB);
- 传输:Cookie 随请求携带(浪费带宽),Web Storage 仅本地存储;
- 易用性:Web Storage API 简洁,Cookie 需手动封装;
- 定位:Cookie 用于服务端交互 (登录态),Web Storage 仅用于本地存储。
核心总结
- 轻量跨端交互(登录态)用 Cookie,需配置
HttpOnly/Secure防攻击; - 本地持久存储用 LocalStorage,临时存储用 SessionStorage;
- 大量数据存储用 IndexedDB,避免 Web SQL(已废弃);
- 核心区分维度:容量、有效期、请求携带、共享范围。
浏览器同源策略
一、同源策略核心定义
1. 核心概念
同源策略是浏览器的安全隔离机制,限制不同源的文档 / 脚本对当前源资源的交互。
✅ 同源要求:协议、域名、端口三者完全一致(缺一则跨域)。
2. 跨域判断示例(基准 URL:http://store.company.com/dir/page.html)
| 对比 URL | 是否跨域 | 核心原因 |
|---|---|---|
| http://store.company.com/dir/inner.html | 同源 | 仅路径不同 |
| https://store.company.com/secure.html | 跨域 | 协议不同(http→https) |
| http://store.company.com:81/dir/etc.html | 跨域 | 端口不同(默认 80→81) |
| http://news.company.com/dir/other.html | 跨域 | 域名不同(store→news) |
3. 同源策略的 3 大限制(高频考点)
❶ 无法访问其他域的 Cookie、LocalStorage、IndexedDB;
❷ 无法操作其他域的 DOM;
❸ 无法发送跨域 AJAX 请求(fetch/XHR)。
二、跨域解决方案
1. CORS(跨域资源共享,最主流)
核心原理
通过服务器设置HTTP 响应头,告知浏览器允许跨域请求,全程由浏览器自动处理,无需前端额外操作(核心在后端)。
分类:简单请求 vs 非简单请求
| 类型 | 判定条件(满足全部) | 核心特点 |
|---|---|---|
| 简单请求 | ① 请求方法:GET/HEAD/POST; ② 头部字段满足CORS安全规范(不改变HEAD的内容) ③ 头信息仅允许:Accept、Content-Type(仅限 3 种值:application/x-www-form-urlencoded、multipart/form-data、text/plain)等 | 直接发请求,携带 Origin 头 |
| 非简单请求 | 不满足简单请求条件(如 PUT/DELETE、自定义头、JSON 格式) | 先发预检请求(OPTIONS) ,验证通过再发正式请求 |
服务器回应的CORS的字段如下:
javascript
Access-Control-Allow-Origin: http://api.bob.com // 允许跨域的源地址
Access-Control-Allow-Methods: GET, POST, PUT // 服务器支持的所有跨域请求的方法
Access-Control-Allow-Headers: X-Custom-Header // 服务器支持的所有头信息字段
Access-Control-Allow-Credentials: true // 表示是否允许发送Cookie
Access-Control-Max-Age: 1728000 // 用来指定本次预检请求的有效期,单位为秒
只要服务器通过了预检请求,在以后每次的CORS请求都会自带一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。在非简单请求中,至少需要设置以下字段:
javascript
'Access-Control-Allow-Origin'
'Access-Control-Allow-Methods'
'Access-Control-Allow-Headers'
核心响应头(后端必设)
- 简单请求:至少设置
Access-Control-Allow-Origin: 允许的源(如http://domain1.com,不可为*当需传 Cookie 时); - 非简单请求:需额外设置
Access-Control-Allow-Methods(允许的方法)、Access-Control-Allow-Headers(允许的自定义头); - 传 Cookie 额外条件:① 前端设
withCredentials: true(axios/XHR);② 后端设Access-Control-Allow-Credentials: true;③Access-Control-Allow-Origin为具体域名(非*)。
优化:减少 OPTIONS 请求
设置 Access-Control-Max-Age: 秒数,缓存预检请求结果(有效期内无需重复预检)。
2. JSONP(兼容性方案,逐步淘汰)
核心原理
利用 <script> 标签无跨域限制 的特性,通过其src属性发送带callback参数的 GET 请求,服务端将数据拼接为callback(数据)的格式返回,前端执行回调函数获取数据。
优缺点
- ✅ 优点:兼容性好(支持老浏览器);
- ❌ 缺点:① 仅支持 GET 方法;② 不安全(易遭受 XSS 攻击)。
3. postMessage(跨窗口 /iframe 跨域)
核心原理
HTML5 新增 API,允许不同源的窗口 /iframe 通过postMessage方法直接传递数据,需指定目标源(保障安全)。
适用场景
- 页面与新打开窗口的数据传递;
- 多窗口间通信;
- 页面与嵌套 iframe 的跨域通信。
4. 代理跨域(Nginx/Node 中间件,实战常用)
核心原理
同源策略仅限制浏览器→服务器,服务器之间无跨域限制。通过搭建代理服务器(与前端同源),转发前端请求到目标跨域服务器,再将结果返回前端。
(1)Nginx 代理跨域 开发模式
server {
listen 81; # 代理服务器端口(与前端同源)
server_name www.domain1.com;
location / {
proxy_pass http://www.domain2.com:8080; # 转发到目标跨域服务器
add_header Access-Control-Allow-Origin http://www.domain1.com; # 允许前端源
add_header Access-Control-Allow-Credentials true; # 支持传Cookie
}
}
(2)Node 中间件代理(如 express+http-proxy-middleware) 生产模式
const express = require('express');
const proxy = require('http-proxy-middleware');
const app = express();
app.use('/', proxy({
target: 'http://domain2.com:8080', // 目标跨域服务器
changeOrigin: true, // 模拟同源请求
onProxyRes: (proxyRes, req, res) => {
res.header('Access-Control-Allow-Origin', 'http://domain1.com');
res.header('Access-Control-Allow-Credentials', 'true');
}
}));
app.listen(3000); // 代理服务器端口(与前端同源)
5. 其他跨域方案(了解即可)
| 方案 | 核心原理 | 适用场景 | 缺点 |
|---|---|---|---|
| document.domain+iframe | 主域相同、子域不同时,强制设置document.domain=主域,实现同域 |
子域跨域(如a.domain.com→b.domain.com) | 仅限主域相同场景 |
| location.hash+iframe | 通过 iframe 的 hash 值传递数据,借助同域中间页转发 | 复杂跨域场景(无主域限制) | 数据量小,逻辑繁琐 |
| window.name+iframe | 利用window.name值在不同域加载后仍保留的特性,通过同域代理页读取 |
跨域传递大量数据(2MB) | 需额外代理页,逻辑复杂 |
| WebSocket | 基于 TCP 全双工通信协议,天然支持跨域 | 实时通信(如聊天、推送) | 需服务端支持 WebSocket |
三、正向代理 vs 反向代理
核心区别:代理的 "设置方" 和 "隐藏对象" 不同
| 维度 | 正向代理 | 反向代理 |
|---|---|---|
| 设置方 | 客户端设置(如浏览器配置代理) | 服务器设置(如 Nginx 配置) |
| 核心目的 | 帮助客户端访问无法直接访问的服务器 | 隐藏真实服务器、负载均衡、缓存 |
| 隐藏对象 | 隐藏真实客户端(服务器不知客户端是谁) | 隐藏真实服务器(客户端不知服务器是谁) |
| 典型场景 | 科学上网、企业内网代理 | 网站负载均衡、跨域代理、CDN |
四、Nginx 核心概念与工作原理
1. 核心定位
轻量级 Web 服务器,可实现反向代理、负载均衡、HTTP 缓存 等功能,核心优势是高性能、高并发。
2. 核心工作原理
- 架构:采用 master+worker 多进程模型;
- master 进程:管理 worker 进程(启动、重启、关闭);
- worker 进程:处理 HTTP 请求(单个 worker 可同时处理大量请求);
- 性能优势:基于 异步事件驱动模型(epoll),而非 Apache 的 "多进程 / 多线程" 模型,减少进程切换开销,支持 10 万 + 并发连接。
核心总结
- 同源策略:协议、域名、端口一致,限制 Cookie/DOM/AJAX 跨域访问;
- 跨域主流方案:① CORS(后端配置,最常用);② 代理跨域(Nginx/Node,实战必备);③ JSONP(兼容老浏览器,仅 GET);
- 代理区别:正向代理(客户端设,藏客户端),反向代理(服务器设,藏服务器);
- Nginx 优势:异步事件驱动、master+worker 架构,高性能支持高并发。
浏览器事件机制
一、核心概念:事件与事件模型
1. 事件定义
用户交互动作(如 click、move)或网页自身操作(如加载、滚动),封装为event对象,包含事件属性(如目标元素)和方法(如阻止冒泡)。
2. 三大事件模型
| 模型 | 事件流 / 特点 | 绑定方式 | 兼容性 |
|---|---|---|---|
| DOM0 级 | 无事件流(部分浏览器支持冒泡),仅支持单事件绑定 | 直接赋值(dom.onclick = fn) |
所有浏览器兼容 |
| IE 事件模型 | 两阶段:事件处理阶段 → 事件冒泡(从目标到 document) | attachEvent('onclick', fn)(多事件按顺序执行) |
仅 IE 浏览器 |
| DOM2 级 | 三阶段:事件捕获 → 目标处理 → 事件冒泡(主流模型) | addEventListener('click', fn, useCapture)(useCapture 默认 false,即冒泡阶段执行) |
现代浏览器(Chrome/Firefox/Safari) |
二、关键操作:阻止事件冒泡 / 传播
- 现代浏览器:
event.stopPropagation()(阻止冒泡和捕获); - IE 浏览器:
event.cancelBubble = true(仅阻止冒泡); - 延伸:
event.stopImmediatePropagation():阻止事件传播 + 阻止目标元素后续绑定的同类型事件执行(比 stopPropagation 更彻底)。
三、事件委托(事件代理)
1. 核心原理
利用事件冒泡机制 ,将子元素的事件监听绑定到父元素,通过event.target获取目标元素,统一处理子元素事件。
2. 核心优势
- ✅ 减少内存消耗(无需给每个子元素绑定事件);
- ✅ 支持动态绑定(新增子元素无需重新绑定事件)。
3. 局限性
- ❌ 不支持无冒泡事件(如 focus、blur);
- ❌ 高消耗事件(如 mousemove、mouseout)不适合(需频繁计算定位);
- ❌ DOM 层级过深会影响性能。
4. 经典实现(列表点击示例)
javascript
document.getElementById('list').addEventListener('click', (e) => {
const target = e.target || e.srcElement; // 兼容IE
if (target.nodeName.toLowerCase() === 'li') { // 匹配目标元素
console.log(target.innerHTML);
}
});
四、同步与异步(事件循环基础)
1. 核心区别
- 同步:执行请求时阻塞等待,直到结果返回再继续;
- 异步:执行请求时不阻塞,结果返回后通过回调通知执行(如定时器、AJAX)。
2. 事件循环(Event Loop,核心考点)
浏览器事件循环(执行顺序)
- 执行同步代码(属于宏任务);
- 同步代码执行完,清空微任务队列(按顺序执行所有微任务);
- 微任务执行完,渲染页面(可选);
- 进入下一轮循环,执行宏任务队列中的第一个任务,重复步骤 1-3。
宏任务 vs 微任务
| 类型 | 包含内容 |
|---|---|
| 宏任务 | script 脚本、setTimeout、setInterval、I/O 操作、UI 渲染、setImmediate(Node) |
| 微任务 | Promise.then/catch/finally、process.nextTick(Node,优先级最高)、MutationObserver |