1. ResizeObserver —— 监听 DOM 尺寸变化
🔍 作用
监听任意 DOM 元素的 content box(内容区域)宽高变化,比 window.onresize 更精准、高效。
🧩 完整示例
<div id="resizable" style="width: 200px; height: 100px; background: lightblue; resize: both; overflow: auto;">
拖动右下角调整大小
</div>
<script>
const target = document.getElementById('resizable');
const ro = new ResizeObserver((entries) => {
for (const entry of entries) {
const { width, height } = entry.contentRect;
console.log(`元素尺寸:${width} x ${height}`);
// 可在此处触发图表重绘、布局调整等
}
});
ro.observe(target);
</script>
📌 参数说明
entries: Array ofResizeObserverEntryentry.target: 被观察的 DOM 元素entry.contentRect:{x, y, width, height},等价于getBoundingClientRect()但不含 border/padding
⚠️ 注意
- 不会因 CSS transform 触发
- 避免在回调中修改被观察元素尺寸(可能引发无限循环)
🌐 兼容性
✅ Chrome 64+ | Firefox 69+ | Safari 13.1+ | Edge 79+
2. IntersectionObserver —— 检测元素是否进入视口
🔍 作用
异步检测目标元素与祖先容器(通常是 viewport)的交叉状态,用于懒加载、曝光统计等。
🧩 完整示例(图片懒加载)
<img data-src="https://example.com/image.jpg" class="lazy" alt="延迟加载">
<script>
const images = document.querySelectorAll('.lazy');
const io = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src; // 加载真实图片
observer.unobserve(img); // 加载后停止监听
}
});
}, {
root: null, // 默认为 viewport
rootMargin: '50px', // 提前 50px 触发
threshold: 0.01 // 只要 1% 进入视口就触发
});
images.forEach(img => io.observe(img));
</script>
📌 关键配置项
root: 容器元素(默认为浏览器视口)rootMargin: 类似 CSS margin,扩展/收缩检测区域threshold: 0~1 的数字或数组,表示交叉比例阈值
🌐 兼容性
✅ 所有现代浏览器(IE 不支持)
3. Page Visibility API —— 判断页面是否可见
🔍 作用
检测用户是否切换到其他标签页或最小化窗口。
🧩 完整示例
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
console.log('页面已隐藏,暂停视频/轮询');
// video.pause();
// clearInterval(pollingInterval);
} else {
console.log('页面恢复可见,继续播放/轮询');
// video.play();
}
});
📌 属性
document.hidden:true表示页面不可见document.visibilityState:'visible' | 'hidden' | 'prerender' | 'unloaded'
🌐 兼容性
✅ 所有浏览器(包括 IE10+)
4. Web Share API —— 调用系统分享面板
🔍 作用
唤起操作系统原生分享菜单(微信、微博、邮件等)
🧩 完整示例
<button id="shareBtn">分享本页</button>
<script>
document.getElementById('shareBtn').addEventListener('click', async () => {
if (!navigator.share) {
alert('当前浏览器不支持 Web Share');
return;
}
try {
await navigator.share({
title: document.title,
text: '快来看这篇好文!',
url: location.href
});
} catch (err) {
console.warn('分享被取消或失败:', err);
}
});
</script>
⚠️ 限制
- 必须在 HTTPS 环境下(localhost 除外)
- 必须由 用户手势(如 click)触发
- 桌面 Safari 支持有限
🌐 兼容性
✅ Android Chrome | iOS Safari 12.2+ | Windows Chrome(部分)
5. Wake Lock API —— 防止屏幕熄灭
🔍 作用
请求保持屏幕常亮(适用于阅读、直播、扫码等场景)
🧩 完整示例
<button id="lockBtn">保持屏幕常亮</button>
<script>
let wakeLock = null;
async function requestWakeLock() {
try {
wakeLock = await navigator.wakeLock.request('screen');
console.log('Wake Lock 已激活');
wakeLock.addEventListener('release', () => {
console.log('Wake Lock 已释放');
});
} catch (err) {
console.error('无法获取 Wake Lock:', err);
}
}
document.getElementById('lockBtn').addEventListener('click', requestWakeLock);
// 页面隐藏时自动释放(最佳实践)
document.addEventListener('visibilitychange', () => {
if (wakeLock !== null && document.hidden) {
wakeLock.release().then(() => wakeLock = null);
}
});
</script>
⚠️ 限制
- 必须 HTTPS + 用户手势
- 仅支持
'screen'类型(音频锁已被移除) - Safari 不支持
🌐 兼容性
✅ Chrome 84+ | Edge 84+ | ❌ Firefox / Safari
6. Broadcast Channel API —— 同源跨标签通信
🔍 作用
在同源(协议+域名+端口相同)的不同页面/iframe 间广播消息
🧩 完整示例(两个标签页同步登录状态)
// 所有页面都执行以下代码
const bc = new BroadcastChannel('auth-channel');
// 发送登录消息(例如登录成功后)
function login(username) {
bc.postMessage({ type: 'login', user: username });
}
// 监听消息
bc.onmessage = (event) => {
if (event.data.type === 'login') {
alert(`其他页面已登录:${event.data.user}`);
// 可刷新 UI 或跳转
}
};
// 示例:点击按钮模拟登录
document.body.innerHTML += '<button onclick="login(\'Alice\')">模拟登录</button>';
📌 特点
- 消息为结构化克隆(支持对象、数组等)
- 不依赖 localStorage,无轮询开销
🌐 兼容性
✅ Chrome 54+ | Firefox 38+ | Edge 79+ | ❌ Safari(17+ 实验性支持)
7. PerformanceObserver —— 监听性能指标
🔍 作用
订阅浏览器性能条目(如 LCP、FCP、CLS),用于真实用户监控(RUM)
🧩 完整示例(上报 LCP)
function sendToAnalytics(metric) {
console.log('上报性能指标:', metric.name, metric.startTime);
// 实际项目中可发往 GA、自建监控系统等
}
const po = new PerformanceObserver((list) => {
list.getEntries().forEach(sendToAnalytics);
});
// 监听 Largest Contentful Paint
po.observe({ type: 'largest-contentful-paint', buffered: true });
// 也可监听 'first-input', 'layout-shift', 'navigation' 等
📌 关键点
buffered: true:获取页面加载过程中已发生的指标- 需在
<head>尽早注册,避免漏掉早期指标
🌐 兼容性
✅ 所有现代浏览器(Web Vitals 标准)
8. requestIdleCallback —— 在空闲时执行任务
🔍 作用
将低优先级任务(如日志、预加载)安排在浏览器空闲帧执行
🧩 完整示例
function logData(deadline) {
// deadline.timeRemaining() 返回剩余空闲时间(毫秒)
while (deadline.timeRemaining() > 0 || deadline.didTimeout) {
if (tasks.length > 0) {
const task = tasks.shift();
processTask(task);
} else {
break;
}
}
if (tasks.length > 0) {
// 任务未完成,继续调度
requestIdleCallback(logData);
}
}
const tasks = ['task1', 'task2', 'task3'];
requestIdleCallback(logData, { timeout: 2000 }); // 最多等 2 秒
⚠️ 注意
- Safari 不支持 → 可用
setTimeout(fn, 0)降级 - 已被
scheduler.postTask逐步取代
🌐 兼容性
✅ Chrome 47+ | Firefox 55+ | ❌ Safari
9. scheduler.postTask —— 优先级任务调度(实验性)
🔍 作用
按优先级(user-blocking, user-visible, background)调度任务
🧩 完整示例
if ('scheduler' in window) {
scheduler.postTask(() => {
console.log('后台任务执行');
}, { priority: 'background' });
scheduler.postTask(() => {
console.log('高优任务执行');
}, { priority: 'user-blocking' });
} else {
// 降级到 setTimeout
setTimeout(() => console.log('降级执行'), 0);
}
🌐 兼容性
⚠️ 仅 Chrome 105+(需开启实验性 Web Platform features)
10. AbortController —— 统一取消异步操作
🔍 作用
提供标准方式取消 fetch、setTimeout、自定义 Promise 等
🧩 完整示例(取消 fetch)
const controller = new AbortController();
const { signal } = controller;
fetch('/api/data', { signal })
.then(res => res.json())
.then(data => console.log(data))
.catch(err => {
if (err.name === 'AbortError') {
console.log('请求被取消');
} else {
console.error('请求失败:', err);
}
});
// 5 秒后自动取消
setTimeout(() => controller.abort(), 5000);
📌 通用模式
任何接受 signal 的 API 都可被取消(如 addEventListener({ signal }))
🌐 兼容性
✅ 所有现代浏览器
11. ReadableStream —— 流式读取数据(如响应体)
🔍 作用
以流(stream)方式逐步读取数据,避免一次性加载大文件导致内存溢出。常用于处理 fetch 响应、实时日志、视频流等。
🧩 完整示例:逐块读取并显示文本
<button id="loadBtn">加载大文本</button>
<pre id="output" style="white-space: pre-wrap; max-height: 300px; overflow: auto;"></pre>
<script>
document.getElementById('loadBtn').addEventListener('click', async () => {
const output = document.getElementById('output');
output.textContent = '正在加载...';
try {
// 模拟一个返回大文本的接口(需 CORS 支持)
const response = await fetch('https://httpbin.org/stream-bytes/10000'); // 返回 10KB 随机字节
if (!response.body) {
throw new Error('ReadableStream not supported');
}
const reader = response.body.getReader();
const decoder = new TextDecoder(); // 将 Uint8Array 转为字符串
let receivedLength = 0;
while (true) {
const { done, value } = await reader.read(); // value 是 Uint8Array
if (done) {
output.textContent += '\n\n✅ 加载完成';
break;
}
receivedLength += value.length;
const chunk = decoder.decode(value, { stream: true }); // 流式解码
output.textContent += chunk;
// 可选:限制输出长度防卡顿
if (receivedLength > 5000) {
output.textContent += '\n...(仅展示前 5KB)';
reader.cancel(); // 主动取消后续读取
break;
}
}
} catch (err) {
console.error('流读取失败:', err);
document.getElementById('output').textContent = '❌ 加载失败: ' + err.message;
}
});
</script>
📌 关键点
response.body是ReadableStream<Uint8Array>reader.read()返回{ done: boolean, value: Uint8Array }- 使用
TextDecoder({ stream: true })处理跨块字符(如中文) - 调用
reader.cancel()可中断读取
⚠️ 注意
- 不适用于 JSON API(因 JSON 需完整解析)
- 适合文本、二进制、SSE(Server-Sent Events)等流式协议
🌐 兼容性
✅ Chrome 43+ | Firefox 65+ | Safari 10.1+ | Edge 79+
12. WritableStream —— 流式写入数据
🔍 作用
将数据分块写入目标(如文件、网络、内存),适用于上传、生成大文件、实时保存草稿等。
🧩 完整示例:创建可下载的流式文本文件
<button id="downloadBtn">生成并下载大文件</button>
<script>
document.getElementById('downloadBtn').addEventListener('click', async () => {
// 创建 WritableStream
const writableStream = new WritableStream({
start(controller) {
console.log('WritableStream 启动');
},
write(chunk, controller) {
console.log('写入块:', chunk);
// 实际项目中可写入文件系统或网络
},
close() {
console.log('流已关闭');
},
abort(reason) {
console.error('流被中止:', reason);
}
});
const writer = writableStream.getWriter();
// 模拟分块写入
for (let i = 0; i < 5; i++) {
await writer.write(`Chunk ${i}\n`);
await new Promise(r => setTimeout(r, 200)); // 模拟延迟
}
await writer.close();
// 💡 实际应用:结合 File System Access API 写入本地文件(见第 14 项)
alert('WritableStream 写入完成(控制台查看日志)');
});
</script>
💡 真实场景:通常与
TransformStream或FileAPI 结合,例如:const fileHandle = await window.showSaveFilePicker(); const writable = await fileHandle.createWritable(); // 然后通过 writable.write(chunk) 写入
🌐 兼容性
✅ Chrome 52+ | Firefox 102+ | Safari 14.1+ | Edge 79+
13. Background Fetch —— PWA 后台静默下载
🔍 作用
即使用户关闭页面,也能在后台下载大文件(如视频课程),支持断点续传。
🧩 完整示例(需 Service Worker)
⚠️ 此 API 必须在 Service Worker 中调用
1. 注册 SW(main.js)
// main.js
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}
2. Service Worker(sw.js)
// sw.js
self.addEventListener('backgroundfetchsuccess', (event) => {
console.log('后台下载成功:', event.id);
// 可通知用户或缓存到 Cache Storage
});
self.addEventListener('backgroundfetchfail', (event) => {
console.error('后台下载失败:', event.id);
});
3. 触发下载(页面中)
// 页面 JS
document.getElementById('downloadVideo').addEventListener('click', async () => {
const registration = await navigator.serviceWorker.ready;
try {
const bgFetch = await registration.backgroundFetch.fetch('course-video', [
'/video1.mp4',
'/video2.mp4'
], {
title: '课程视频下载中...',
icons: [{ src: '/icon.png', sizes: '128x128' }]
});
console.log('后台下载已启动:', bgFetch.id);
} catch (err) {
console.error('无法启动后台下载:', err);
}
});
⚠️ 限制
- 仅限 PWA 安装后使用
- 必须 HTTPS
- 用户需授权(首次会弹窗)
- 目前 仅 Chrome/Edge 支持
🌐 兼容性
⚠️ Chrome 71+ | ❌ Firefox / Safari
14. File System Access API —— 读写本地真实文件
🔍 作用
让用户直接打开/保存本地文件(绕过 <input type="file"> 的沙盒限制),适用于 Web IDE、文档编辑器。
🧩 完整示例:打开文件 → 编辑 → 保存回原文件
<textarea id="editor" style="width:100%;height:200px;"></textarea><br>
<button id="openBtn">打开文件</button>
<button id="saveBtn">保存文件</button>
<script>
let currentFileHandle = null;
// 打开文件
document.getElementById('openBtn').addEventListener('click', async () => {
try {
[currentFileHandle] = await window.showOpenFilePicker({
types: [{
description: '文本文件',
accept: { 'text/plain': ['.txt'] }
}],
multiple: false
});
const file = await currentFileHandle.getFile();
const contents = await file.text();
document.getElementById('editor').value = contents;
} catch (err) {
if (err.name !== 'AbortError') console.error(err);
}
});
// 保存文件
document.getElementById('saveBtn').addEventListener('click', async () => {
if (!currentFileHandle) {
alert('请先打开一个文件');
return;
}
const writable = await currentFileHandle.createWritable();
await writable.write(document.getElementById('editor').value);
await writable.close();
alert('✅ 文件已保存!');
});
</script>
⚠️ 安全限制
- 必须由 用户手势(如点击)触发
- 必须 HTTPS
- 首次操作会弹出系统文件选择器(用户授权)
🌐 兼容性
✅ Chrome 86+ | Edge 86+ | ❌ Firefox / Safari(部分实验性)
15. Clipboard API —— 安全读写剪贴板
🔍 作用
异步读写剪贴板内容,替代不安全的 execCommand('copy')
🧩 完整示例
<input id="text" value="要复制的文本">
<button id="copyBtn">复制</button>
<button id="pasteBtn">粘贴</button>
<p id="result"></p>
<script>
// 复制
document.getElementById('copyBtn').addEventListener('click', async () => {
try {
await navigator.clipboard.writeText(document.getElementById('text').value);
document.getElementById('result').textContent = '✅ 已复制到剪贴板';
} catch (err) {
console.error('复制失败:', err);
document.getElementById('result').textContent = '❌ 复制失败,请检查权限';
}
});
// 粘贴
document.getElementById('pasteBtn').addEventListener('click', async () => {
try {
const text = await navigator.clipboard.readText();
document.getElementById('result').textContent = '粘贴内容: ' + text;
} catch (err) {
console.error('粘贴失败:', err);
document.getElementById('result').textContent = '❌ 无法读取剪贴板';
}
});
</script>
⚠️ 权限
- 写入:只需用户手势(如 click)
- 读取:部分浏览器要求额外权限(Chrome 会自动允许,Safari 可能弹窗)
🌐 兼容性
✅ Chrome 66+ | Firefox 63+ | Safari 13.1+ | Edge 79+
16. URLSearchParams —— 解析/构造 URL 查询参数
🔍 作用
无需正则,轻松操作 ?key=value&foo=bar 类型的查询字符串
🧩 完整示例
// 从当前 URL 解析
const params = new URLSearchParams(window.location.search);
// 获取参数
console.log(params.get('page')); // "2"
// 修改参数
params.set('page', '3');
params.append('tag', 'js');
params.delete('utm_source');
// 生成新 URL
const newUrl = `${window.location.pathname}?${params.toString()}`;
console.log(newUrl); // "/path?page=3&tag=js"
// 应用到历史记录(不刷新页面)
history.replaceState(null, '', newUrl);
📌 方法
.get(key)/.getAll(key).set(key, value)/.append(key, value).has(key)/.delete(key).toString()→"key1=val1&key2=val2"
🌐 兼容性
✅ 所有现代浏览器(IE 不支持)
17. structuredClone() —— 原生深拷贝
🔍 作用
深度克隆对象,支持 Date、RegExp、Map、Set、ArrayBuffer、嵌套对象、循环引用等
🧩 完整示例
const original = {
name: 'Alice',
birth: new Date('1990-01-01'),
tags: new Set(['dev', 'js']),
meta: { count: 100 },
self: null // 循环引用占位
};
original.self = original; // 创建循环引用
try {
const copy = structuredClone(original);
console.log(copy.name === original.name); // true(值相同)
console.log(copy.birth !== original.birth); // true(新 Date 对象)
console.log(copy.meta !== original.meta); // true(深拷贝)
console.log(copy.self === copy); // true(循环引用正确保留)
} catch (err) {
console.error('克隆失败:', err);
}
⚠️ 不支持类型
- 函数(Function)
- Symbol
- DOM 节点
- Proxy
🌐 兼容性
✅ Chrome 98+ | Firefox 94+ | Safari 15.4+ | Edge 98+
💡 降级方案:
JSON.parse(JSON.stringify(obj))(但丢失函数/Date/undefined 等)
18. Intl.NumberFormat —— 国际化数字格式化
🔍 作用
按地区习惯格式化数字(货币、千分位、百分比等)
🧩 完整示例
const number = 1234567.89;
// 中文人民币
console.log(new Intl.NumberFormat('zh-CN', {
style: 'currency',
currency: 'CNY'
}).format(number)); // "¥1,234,567.89"
// 美元
console.log(new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(number)); // "$1,234,567.89"
// 百分比
console.log(new Intl.NumberFormat('en-US', {
style: 'percent',
minimumFractionDigits: 2
}).format(0.8765)); // "87.65%"
// 千分位(无单位)
console.log(new Intl.NumberFormat('de-DE').format(1234567)); // "1.234.567"
🌐 兼容性
✅ 所有现代浏览器(包括 IE11)
19. EyeDropper API —— 浏览器吸管工具
🔍 作用
调用系统级取色器,获取屏幕任意像素的 HEX 颜色值
🧩 完整示例
<button id="pickColor">吸取屏幕颜色</button>
<div id="colorBox" style="width:100px;height:100px;margin-top:10px;"></div>
<script>
document.getElementById('pickColor').addEventListener('click', async () => {
if (!window.EyeDropper) {
alert('当前浏览器不支持 EyeDropper API');
return;
}
try {
const eyeDropper = new EyeDropper();
const result = await eyeDropper.open(); // 用户点击后出现取色器
document.getElementById('colorBox').style.backgroundColor = result.sRGBHex;
console.log('选取的颜色:', result.sRGBHex);
} catch (err) {
if (err.name !== 'AbortError') console.error(err);
}
});
</script>
⚠️ 限制
- 必须由用户手势触发
- 仅返回 sRGB 格式(#RRGGBB)
- 无法跨显示器/应用取色(仅限当前浏览器窗口)
🌐 兼容性
✅ Chrome 95+ | Edge 95+ | ❌ Firefox / Safari
20. WebCodecs API —— 原生音视频编解码
🔍 作用
直接访问硬件编解码器,实现低延迟、高性能视频处理(如 4K 60fps 播放、视频编辑)
🧩 完整示例:解码 VP9 视频帧并绘制到 Canvas
⚠️ 需要有效的视频流(此处仅为框架演示)
<canvas id="videoCanvas" width="640" height="360"></canvas>
<script>
const canvas = document.getElementById('videoCanvas');
const ctx = canvas.getContext('2d');
const decoder = new VideoDecoder({
output: (frame) => {
// 将解码后的视频帧绘制到 canvas
ctx.drawImage(frame, 0, 0);
frame.close(); // 重要:释放帧内存
},
error: (e) => {
console.error('解码错误:', e);
}
});
// 配置解码器(需与视频编码匹配)
decoder.configure({
codec: 'vp09.00.10.08', // VP9 Profile 0
codedWidth: 640,
codedHeight: 360
});
// 模拟:从 ReadableStream 读取视频 chunk 并 enqueue
// 实际项目中需从 fetch 或 MediaSource 获取
// decoder.decode(chunk); // chunk 为 EncodedVideoChunk
// 清理
window.addEventListener('beforeunload', () => {
decoder.close();
});
</script>
📌 关键类
VideoDecoder/AudioDecoderVideoEncoder/AudioEncoderEncodedVideoChunk/EncodedAudioChunk
⚠️ 注意
- 高级 API,适合音视频专业应用
- 需处理大量底层细节(SPS/PPS、时间戳、关键帧等)
🌐 兼容性
✅ Chrome 94+ | Edge 94+ | ❌ Firefox / Safari
🎯 总结建议(2025 年实践指南)
| 推荐等级 | API 列表 | 说明 |
|---|---|---|
| 🔥 强烈推荐 | ResizeObserver, IntersectionObserver, AbortController, URLSearchParams, Intl.NumberFormat, Clipboard | 高兼容、高实用、零成本 |
| ✅ 按需使用 | Page Visibility, Broadcast Channel, PerformanceObserver, structuredClone | 场景明确,现代项目常用 |
| ⚠️ 谨慎使用 | Wake Lock, EyeDropper, WebCodecs, File System Access, Background Fetch | 功能强大但兼容性有限,需降级方案 |
💡 最佳实践:
- 使用 Can I Use 检查目标用户浏览器支持情况
- 对实验性 API 提供优雅降级(如
if ('wakeLock' in navigator))- 敏感 API(如文件、剪贴板)始终在用户手势后调用