为什么 Web API 是浏览器环境的核心
JavaScript 的强大之处不仅在于语言本身,更在于浏览器提供的丰富 Web API。从网络请求到文件处理,从页面渲染到性能监控,这些 API 让 JavaScript 能够操作浏览器、实现复杂的交互效果。
这篇文章解析现代前端开发中最常用的 Web API。
一、fetch API
1.1 基本用法
// GET 请求
const response = await fetch('/api/users');
const users = await response.json();
// POST 请求
const response = await fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'Alice', age: 30 })
});
const newUser = await response.json();
1.2 Request 和 Response 对象
// 创建 Request 对象
const request = new Request('/api/users', {
method: 'GET',
headers: new Headers({ 'Accept': 'application/json' })
});
// Response 对象属性
const response = await fetch(request);
console.log(response.ok); // boolean
console.log(response.status); // 200
console.log(response.headers); // Headers 对象
// 克隆 Response(Response 只能读取一次)
const cloned = response.clone();
1.3 流式处理
// 流式读取大文件
const response = await fetch('/large-file.txt');
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
console.log(`Received ${value.length} bytes`);
}
二、URLSearchParams
2.1 基本操作
const params = new URLSearchParams();
params.set('name', 'Alice');
params.append('tag', 'developer');
params.append('tag', 'engineer');
console.log(params.toString()); // 'name=Alice&tag=developer&tag=engineer'
// 获取
console.log(params.get('name')); // 'Alice'
console.log(params.getAll('tag')); // ['developer', 'engineer']
// 检查
console.log(params.has('name')); // true
// 删除
params.delete('tag');
2.2 实际应用
// 构建查询参数
const params = new URLSearchParams({
page: 1,
limit: 10,
sort: 'name'
});
const url = `/api/users?${params}`;
// 解析 URL 参数
const url = new URL(window.location.href);
const page = url.searchParams.get('page');
三、IntersectionObserver
3.1 懒加载图片
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
}, {
rootMargin: '50px',
threshold: 0.1
});
document.querySelectorAll('img[data-src]').forEach(img => {
observer.observe(img);
});
3.2 曝光埋点
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const element = entry.target;
const eventName = element.dataset.event;
analytics.track(eventName, {
visibility: entry.intersectionRatio
});
}
});
}, {
threshold: [0, 0.5, 1]
});
document.querySelectorAll('[data-event]').forEach(el => {
observer.observe(el);
});
四、MutationObserver
4.1 监听 DOM 变化
const observer = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
console.log('Mutation type:', mutation.type);
console.log('Changed nodes:', mutation.addedNodes);
});
});
observer.observe(document.body, {
childList: true, // 监听子节点添加/删除
subtree: true, // 监听所有后代
attributes: true, // 监听属性变化
attributeOldValue: true
});
// 断开观察
observer.disconnect();
4.2 实际应用
// 检测某个元素是否被添加到 DOM
const observer = new MutationObserver((mutations, obs) => {
const target = document.querySelector('#target');
if (target) {
console.log('Target element added to DOM');
obs.disconnect(); // 找到后停止观察
}
});
observer.observe(document.body, { childList: true, subtree: true });
五、requestAnimationFrame
5.1 动画基础
let start = null;
const duration = 1000;
function animate(timestamp) {
if (!start) start = timestamp;
const progress = timestamp - start;
const element = document.querySelector('.moving');
element.style.transform = `translateX(${progress}px)`;
if (progress < duration) {
requestAnimationFrame(animate);
}
}
requestAnimationFrame(animate);
5.2 与 setInterval 的对比
// setInterval:不管浏览器状态,可能丢帧
setInterval(() => {
updatePosition();
}, 16); // 约 60fps,但不稳定
// requestAnimationFrame:与浏览器刷新同步,更流畅
function gameLoop(timestamp) {
updatePosition();
requestAnimationFrame(gameLoop);
}
requestAnimationFrame(gameLoop);
六、structuredClone
6.1 深拷贝对象
const original = {
name: 'Alice',
nested: { value: 1 },
date: new Date()
};
const clone = structuredClone(original);
console.log(clone.name); // 'Alice'
console.log(clone.nested.value); // 1
console.log(clone.date instanceof Date); // true
6.2 支持的类型
// 支持:Date、Map、Set、ArrayBuffer、TypedArray、Error
const obj = {
map: new Map([['a', 1]]),
set: new Set([1, 2, 3]),
date: new Date(),
error: new Error('test')
};
const clone = structuredClone(obj);
console.log(clone.map.get('a')); // 1
console.log(clone.set.has(2)); // true